@@ -168,25 +168,6 @@ static int find_profile_by_name(char *profile_name,
return 1;
}

static int find_profile_by_num(unsigned profile_num,
SRTP_PROTECTION_PROFILE **pptr)
{
SRTP_PROTECTION_PROFILE *p;

p=srtp_known_profiles;
while(p->name)
{
if(p->id == profile_num)
{
*pptr=p;
return 0;
}
p++;
}

return 1;
}

static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTECTION_PROFILE) **out)
{
STACK_OF(SRTP_PROTECTION_PROFILE) *profiles;
@@ -209,11 +190,19 @@ static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTE
if(!find_profile_by_name(ptr,&p,
col ? col-ptr : (int)strlen(ptr)))
{
if (sk_SRTP_PROTECTION_PROFILE_find(profiles,p) >= 0)
{
SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
sk_SRTP_PROTECTION_PROFILE_free(profiles);
return 1;
}

sk_SRTP_PROTECTION_PROFILE_push(profiles,p);
}
else
{
SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
sk_SRTP_PROTECTION_PROFILE_free(profiles);
return 1;
}

@@ -305,13 +294,12 @@ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int max

int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al)
{
SRTP_PROTECTION_PROFILE *cprof,*sprof;
STACK_OF(SRTP_PROTECTION_PROFILE) *clnt=0,*srvr;
SRTP_PROTECTION_PROFILE *sprof;
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
int ct;
int mki_len;
int i,j;
int id;
int ret;
int i, srtp_pref;
unsigned int id;

/* Length value + the MKI length */
if(len < 3)
@@ -341,22 +329,32 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al
return 1;
}

srvr=SSL_get_srtp_profiles(s);
s->srtp_profile = NULL;
/* Search all profiles for a match initially */
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);

clnt=sk_SRTP_PROTECTION_PROFILE_new_null();

while(ct)
{
n2s(d,id);
ct-=2;
len-=2;

if(!find_profile_by_num(id,&cprof))
/*
* Only look for match in profiles of higher preference than
* current match.
* If no profiles have been have been configured then this
* does nothing.
*/
for (i = 0; i < srtp_pref; i++)
{
sk_SRTP_PROTECTION_PROFILE_push(clnt,cprof);
}
else
{
; /* Ignore */
sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
if (sprof->id == id)
{
s->srtp_profile = sprof;
srtp_pref = i;
break;
}
}
}

@@ -371,36 +369,7 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al
return 1;
}

srvr=SSL_get_srtp_profiles(s);

/* Pick our most preferred profile. If no profiles have been
configured then the outer loop doesn't run
(sk_SRTP_PROTECTION_PROFILE_num() = -1)
and so we just return without doing anything */
for(i=0;i<sk_SRTP_PROTECTION_PROFILE_num(srvr);i++)
{
sprof=sk_SRTP_PROTECTION_PROFILE_value(srvr,i);

for(j=0;j<sk_SRTP_PROTECTION_PROFILE_num(clnt);j++)
{
cprof=sk_SRTP_PROTECTION_PROFILE_value(clnt,j);

if(cprof->id==sprof->id)
{
s->srtp_profile=sprof;
*al=0;
ret=0;
goto done;
}
}
}

ret=0;

done:
if(clnt) sk_SRTP_PROTECTION_PROFILE_free(clnt);

return ret;
return 0;
}

int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen)
@@ -84,6 +84,8 @@ extern "C" {
#endif

#define DTLS1_VERSION 0xFEFF
#define DTLS_MAX_VERSION DTLS1_VERSION

#define DTLS1_BAD_VER 0x0100

#if 0
@@ -284,4 +286,3 @@ typedef struct dtls1_record_data_st
}
#endif
#endif

@@ -125,9 +125,11 @@ static const SSL_METHOD *ssl23_get_client_method(int ver)
if (ver == SSL2_VERSION)
return(SSLv2_client_method());
#endif
#ifndef OPENSSL_NO_SSL3
if (ver == SSL3_VERSION)
return(SSLv3_client_method());
else if (ver == TLS1_VERSION)
#endif
if (ver == TLS1_VERSION)
return(TLSv1_client_method());
else if (ver == TLS1_1_VERSION)
return(TLSv1_1_client_method());
@@ -698,6 +700,7 @@ static int ssl23_get_server_hello(SSL *s)
{
/* we have sslv3 or tls1 (server hello or alert) */

#ifndef OPENSSL_NO_SSL3
if ((p[2] == SSL3_VERSION_MINOR) &&
!(s->options & SSL_OP_NO_SSLv3))
{
@@ -712,7 +715,9 @@ static int ssl23_get_server_hello(SSL *s)
s->version=SSL3_VERSION;
s->method=SSLv3_client_method();
}
else if ((p[2] == TLS1_VERSION_MINOR) &&
else
#endif
if ((p[2] == TLS1_VERSION_MINOR) &&
!(s->options & SSL_OP_NO_TLSv1))
{
s->version=TLS1_VERSION;
@@ -736,6 +741,9 @@ static int ssl23_get_server_hello(SSL *s)
goto err;
}

/* ensure that TLS_MAX_VERSION is up-to-date */
OPENSSL_assert(s->version <= TLS_MAX_VERSION);

if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING)
{
/* fatal alert */
@@ -127,9 +127,11 @@ static const SSL_METHOD *ssl23_get_server_method(int ver)
if (ver == SSL2_VERSION)
return(SSLv2_server_method());
#endif
#ifndef OPENSSL_NO_SSL3
if (ver == SSL3_VERSION)
return(SSLv3_server_method());
else if (ver == TLS1_VERSION)
#endif
if (ver == TLS1_VERSION)
return(TLSv1_server_method());
else if (ver == TLS1_1_VERSION)
return(TLSv1_1_server_method());
@@ -421,6 +423,9 @@ int ssl23_get_client_hello(SSL *s)
}
}

/* ensure that TLS_MAX_VERSION is up-to-date */
OPENSSL_assert(s->version <= TLS_MAX_VERSION);

#ifdef OPENSSL_FIPS
if (FIPS_mode() && (s->version < TLS1_VERSION))
{
@@ -597,6 +602,12 @@ int ssl23_get_client_hello(SSL *s)
if ((type == 2) || (type == 3))
{
/* we have SSLv3/TLSv1 (type 2: SSL2 style, type 3: SSL3/TLS style) */
s->method = ssl23_get_server_method(s->version);
if (s->method == NULL)
{
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
goto err;
}

if (!ssl_init_wbio_buffer(s,1)) goto err;

@@ -624,14 +635,6 @@ int ssl23_get_client_hello(SSL *s)
s->s3->rbuf.left=0;
s->s3->rbuf.offset=0;
}
if (s->version == TLS1_2_VERSION)
s->method = TLSv1_2_server_method();
else if (s->version == TLS1_1_VERSION)
s->method = TLSv1_1_server_method();
else if (s->version == TLS1_VERSION)
s->method = TLSv1_server_method();
else
s->method = SSLv3_server_method();
#if 0 /* ssl3_get_client_hello does this */
s->client_version=(v[0]<<8)|v[1];
#endif
@@ -391,6 +391,8 @@ long ssl2_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_GET_SESSION_REUSED:
ret=s->hit;
break;
case SSL_CTRL_CHECK_PROTO_VERSION:
return ssl3_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, larg, parg);
default:
break;
}
@@ -437,7 +439,7 @@ int ssl2_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p)
if (p != NULL)
{
l=c->id;
if ((l & 0xff000000) != 0x02000000) return(0);
if ((l & 0xff000000) != 0x02000000 && l != SSL3_CK_FALLBACK_SCSV) return(0);
p[0]=((unsigned char)(l>>16L))&0xFF;
p[1]=((unsigned char)(l>> 8L))&0xFF;
p[2]=((unsigned char)(l ))&0xFF;
@@ -53,6 +53,7 @@
*
*/

#include "../crypto/constant_time_locl.h"
#include "ssl_locl.h"

#include <openssl/md5.h>
@@ -67,37 +68,6 @@
* supported by TLS.) */
#define MAX_HASH_BLOCK_SIZE 128

/* Some utility functions are needed:
*
* These macros return the given value with the MSB copied to all the other
* bits. They use the fact that arithmetic shift shifts-in the sign bit.
* However, this is not ensured by the C standard so you may need to replace
* them with something else on odd CPUs. */
#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) )
#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x)))

/* constant_time_lt returns 0xff if a<b and 0x00 otherwise. */
static unsigned constant_time_lt(unsigned a, unsigned b)
{
a -= b;
return DUPLICATE_MSB_TO_ALL(a);
}

/* constant_time_ge returns 0xff if a>=b and 0x00 otherwise. */
static unsigned constant_time_ge(unsigned a, unsigned b)
{
a -= b;
return DUPLICATE_MSB_TO_ALL(~a);
}

/* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */
static unsigned char constant_time_eq_8(unsigned a, unsigned b)
{
unsigned c = a ^ b;
c--;
return DUPLICATE_MSB_TO_ALL_8(c);
}

/* ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
* record in |rec| by updating |rec->length| in constant time.
*
@@ -126,8 +96,8 @@ int ssl3_cbc_remove_padding(const SSL* s,
padding_length = good & (padding_length+1);
rec->length -= padding_length;
rec->type |= padding_length<<8; /* kludge: pass padding length */
return (int)((good & 1) | (~good & -1));
}
return constant_time_select_int(good, 1, -1);
}

/* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
* record in |rec| in constant time and returns 1 if the padding is valid and
@@ -208,28 +178,22 @@ int tls1_cbc_remove_padding(const SSL* s,

for (i = 0; i < to_check; i++)
{
unsigned char mask = constant_time_ge(padding_length, i);
unsigned char mask = constant_time_ge_8(padding_length, i);
unsigned char b = rec->data[rec->length-1-i];
/* The final |padding_length+1| bytes should all have the value
* |padding_length|. Therefore the XOR should be zero. */
good &= ~(mask&(padding_length ^ b));
}

/* If any of the final |padding_length+1| bytes had the wrong value,
* one or more of the lower eight bits of |good| will be cleared. We
* AND the bottom 8 bits together and duplicate the result to all the
* bits. */
good &= good >> 4;
good &= good >> 2;
good &= good >> 1;
good <<= sizeof(good)*8-1;
good = DUPLICATE_MSB_TO_ALL(good);

* one or more of the lower eight bits of |good| will be cleared.
*/
good = constant_time_eq(0xff, good & 0xff);
padding_length = good & (padding_length+1);
rec->length -= padding_length;
rec->type |= padding_length<<8; /* kludge: pass padding length */

return (int)((good & 1) | (~good & -1));
return constant_time_select_int(good, 1, -1);
}

/* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
@@ -296,8 +260,8 @@ void ssl3_cbc_copy_mac(unsigned char* out,
memset(rotated_mac, 0, md_size);
for (i = scan_start, j = 0; i < orig_len; i++)
{
unsigned char mac_started = constant_time_ge(i, mac_start);
unsigned char mac_ended = constant_time_ge(i, mac_end);
unsigned char mac_started = constant_time_ge_8(i, mac_start);
unsigned char mac_ended = constant_time_ge_8(i, mac_end);
unsigned char b = rec->data[i];
rotated_mac[j++] |= b & mac_started & ~mac_ended;
j &= constant_time_lt(j,md_size);
@@ -683,12 +647,12 @@ void ssl3_cbc_digest_record(
b = data[k-header_length];
k++;

is_past_c = is_block_a & constant_time_ge(j, c);
is_past_cp1 = is_block_a & constant_time_ge(j, c+1);
is_past_c = is_block_a & constant_time_ge_8(j, c);
is_past_cp1 = is_block_a & constant_time_ge_8(j, c+1);
/* If this is the block containing the end of the
* application data, and we are at the offset for the
* 0x80 value, then overwrite b with 0x80. */
b = (b&~is_past_c) | (0x80&is_past_c);
b = constant_time_select_8(is_past_c, 0x80, b);
/* If this the the block containing the end of the
* application data and we're past the 0x80 value then
* just write zero. */
@@ -704,7 +668,8 @@ void ssl3_cbc_digest_record(
if (j >= md_block_size - md_length_size)
{
/* If this is index_b, write a length byte. */
b = (b&~is_block_b) | (is_block_b&length_bytes[j-(md_block_size-md_length_size)]);
b = constant_time_select_8(
is_block_b, length_bytes[j-(md_block_size-md_length_size)], b);
}
block[j] = b;
}

Large diffs are not rendered by default.

@@ -900,7 +900,7 @@ int ssl3_alert_code(int code)
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
case SSL_AD_INAPPROPRIATE_FALLBACK:return(TLS1_AD_INAPPROPRIATE_FALLBACK);
default: return(-1);
}
}

@@ -3355,6 +3355,33 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
#endif

#endif /* !OPENSSL_NO_TLSEXT */

case SSL_CTRL_CHECK_PROTO_VERSION:
/* For library-internal use; checks that the current protocol
* is the highest enabled version (according to s->ctx->method,
* as version negotiation may have changed s->method). */
if (s->version == s->ctx->method->version)
return 1;
/* Apparently we're using a version-flexible SSL_METHOD
* (not at its highest protocol version). */
if (s->ctx->method->version == SSLv23_method()->version)
{
#if TLS_MAX_VERSION != TLS1_2_VERSION
# error Code needs update for SSLv23_method() support beyond TLS1_2_VERSION.
#endif
if (!(s->options & SSL_OP_NO_TLSv1_2))
return s->version == TLS1_2_VERSION;
if (!(s->options & SSL_OP_NO_TLSv1_1))
return s->version == TLS1_1_VERSION;
if (!(s->options & SSL_OP_NO_TLSv1))
return s->version == TLS1_VERSION;
if (!(s->options & SSL_OP_NO_SSLv3))
return s->version == SSL3_VERSION;
if (!(s->options & SSL_OP_NO_SSLv2))
return s->version == SSL2_VERSION;
}
return 0; /* Unexpected state; fail closed. */

default:
break;
}
@@ -3714,6 +3741,7 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
break;
#endif
#endif

default:
return(0);
}
@@ -3822,10 +3850,15 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
emask_k = cert->export_mask_k;
emask_a = cert->export_mask_a;
#ifndef OPENSSL_NO_SRP
mask_k=cert->mask_k | s->srp_ctx.srp_Mask;
emask_k=cert->export_mask_k | s->srp_ctx.srp_Mask;
if (s->srp_ctx.srp_Mask & SSL_kSRP)
{
mask_k |= SSL_kSRP;
emask_k |= SSL_kSRP;
mask_a |= SSL_aSRP;
emask_a |= SSL_aSRP;
}
#endif

#ifdef KSSL_DEBUG
/* printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);*/
#endif /* KSSL_DEBUG */
@@ -4291,4 +4324,3 @@ long ssl_get_algorithm2(SSL *s)
return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
return alg2;
}

@@ -273,6 +273,12 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
return(n);
}

/* MAX_EMPTY_RECORDS defines the number of consecutive, empty records that will
* be processed per call to ssl3_get_record. Without this limit an attacker
* could send empty records at a faster rate than we can process and cause
* ssl3_get_record to loop forever. */
#define MAX_EMPTY_RECORDS 32

/* Call this to get a new input record.
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
@@ -293,6 +299,7 @@ static int ssl3_get_record(SSL *s)
short version;
unsigned mac_size, orig_len;
size_t extra;
unsigned empty_record_count = 0;

rr= &(s->s3->rrec);
sess=s->session;
@@ -523,7 +530,17 @@ printf("\n");
s->packet_length=0;

/* just read a 0 length packet */
if (rr->length == 0) goto again;
if (rr->length == 0)
{
empty_record_count++;
if (empty_record_count > MAX_EMPTY_RECORDS)
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_RECORD_TOO_SMALL);
goto f_err;
}
goto again;
}

#if 0
fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type, rr->length);
@@ -154,6 +154,7 @@
#include <stdio.h>
#include "ssl_locl.h"
#include "kssl_lcl.h"
#include "../crypto/constant_time_locl.h"
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <openssl/objects.h>
@@ -410,9 +411,8 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SW_CERT_B:
/* Check if it is anon DH or anon ECDH, */
/* normal PSK or KRB5 or SRP */
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
&& !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aKRB5|SSL_aSRP))
&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
{
ret=ssl3_send_server_certificate(s);
if (ret <= 0) goto end;
@@ -515,7 +515,9 @@ int ssl3_accept(SSL *s)
* (against the specs, but s3_clnt.c accepts this for SSL 3) */
!(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
/* never request cert in Kerberos ciphersuites */
(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) ||
/* don't request certificate for SRP auth */
(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
/* With normal PSK Certificates and
* Certificate Requests are omitted */
|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
@@ -1846,7 +1848,7 @@ int ssl3_send_server_key_exchange(SSL *s)
n+=2+nr[i];
}

if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP))
&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
{
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
@@ -2166,6 +2168,10 @@ int ssl3_get_client_key_exchange(SSL *s)
#ifndef OPENSSL_NO_RSA
if (alg_k & SSL_kRSA)
{
unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
int decrypt_len;
unsigned char decrypt_good, version_good;

/* FIX THIS UP EAY EAY EAY EAY */
if (s->s3->tmp.use_rsa_tmp)
{
@@ -2213,54 +2219,61 @@ int ssl3_get_client_key_exchange(SSL *s)
n=i;
}

i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);

al = -1;

if (i != SSL_MAX_MASTER_KEY_LENGTH)
{
al=SSL_AD_DECODE_ERROR;
/* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */
}

if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
{
/* The premaster secret must contain the same version number as the
* ClientHello to detect version rollback attacks (strangely, the
* protocol does not offer such protection for DH ciphersuites).
* However, buggy clients exist that send the negotiated protocol
* version instead if the server does not support the requested
* protocol version.
* If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
(p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff))))
{
al=SSL_AD_DECODE_ERROR;
/* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */
/* We must not leak whether a decryption failure occurs because
* of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see
* RFC 2246, section 7.4.7.1). The code follows that advice of
* the TLS RFC and generates a random premaster secret for the
* case that the decrypt fails. See
* https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */

/* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
* (http://eprint.iacr.org/2003/052/) exploits the version
* number check as a "bad version oracle" -- an alert would
* reveal that the plaintext corresponding to some ciphertext
* made up by the adversary is properly formatted except
* that the version number is wrong. To avoid such attacks,
* we should treat this just like any other decryption error. */
}
/* should be RAND_bytes, but we cannot work around a failure. */
if (RAND_pseudo_bytes(rand_premaster_secret,
sizeof(rand_premaster_secret)) <= 0)
goto err;
decrypt_len = RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
ERR_clear_error();

/* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH.
* decrypt_good will be 0xff if so and zero otherwise. */
decrypt_good = constant_time_eq_int_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH);

/* If the version in the decrypted pre-master secret is correct
* then version_good will be 0xff, otherwise it'll be zero.
* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
* (http://eprint.iacr.org/2003/052/) exploits the version
* number check as a "bad version oracle". Thus version checks
* are done in constant time and are treated like any other
* decryption error. */
version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8));
version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff));

/* The premaster secret must contain the same version number as
* the ClientHello to detect version rollback attacks
* (strangely, the protocol does not offer such protection for
* DH ciphersuites). However, buggy clients exist that send the
* negotiated protocol version instead if the server does not
* support the requested protocol version. If
* SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
{
unsigned char workaround_good;
workaround_good = constant_time_eq_8(p[0], (unsigned)(s->version>>8));
workaround_good &= constant_time_eq_8(p[1], (unsigned)(s->version&0xff));
version_good |= workaround_good;
}

/* Both decryption and version must be good for decrypt_good
* to remain non-zero (0xff). */
decrypt_good &= version_good;

/* Now copy rand_premaster_secret over p using
* decrypt_good_mask. */
for (i = 0; i < (int) sizeof(rand_premaster_secret); i++)
{
p[i] = constant_time_select_8(decrypt_good, p[i],
rand_premaster_secret[i]);
}

if (al != -1)
{
/* Some decryption failure -- use random value instead as countermeasure
* against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding
* (see RFC 2246, section 7.4.7.1). */
ERR_clear_error();
i = SSL_MAX_MASTER_KEY_LENGTH;
p[0] = s->client_version >> 8;
p[1] = s->client_version & 0xff;
if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */
goto err;
}

s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,
@@ -130,13 +130,17 @@ extern "C" {
#define SRTP_NULL_SHA1_80 0x0005
#define SRTP_NULL_SHA1_32 0x0006

#ifndef OPENSSL_NO_SRTP

int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles);
int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles);
SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s);

STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl);
SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s);

#endif

#ifdef __cplusplus
}
#endif
@@ -213,16 +213,16 @@ $ ENDIF
$!
$! Define The Different SSL "library" Files.
$!
$ LIB_SSL = "s2_meth,s2_srvr,s2_clnt,s2_lib,s2_enc,s2_pkt,"+ -
"s3_meth,s3_srvr,s3_clnt,s3_lib,s3_enc,s3_pkt,s3_both,s3_cbc,"+ -
"s23_meth,s23_srvr,s23_clnt,s23_lib,s23_pkt,"+ -
"t1_meth,t1_srvr,t1_clnt,t1_lib,t1_enc,"+ -
"d1_meth,d1_srvr,d1_clnt,d1_lib,d1_pkt,"+ -
$ LIB_SSL = "s2_meth, s2_srvr, s2_clnt, s2_lib, s2_enc, s2_pkt,"+ -
"s3_meth, s3_srvr, s3_clnt, s3_lib, s3_enc, s3_pkt, s3_both, s3_cbc,"+ -
"s23_meth,s23_srvr,s23_clnt,s23_lib, s23_pkt,"+ -
"t1_meth, t1_srvr, t1_clnt, t1_lib, t1_enc,"+ -
"d1_meth, d1_srvr, d1_clnt, d1_lib, d1_pkt,"+ -
"d1_both,d1_enc,d1_srtp,"+ -
"ssl_lib,ssl_err2,ssl_cert,ssl_sess,"+ -
"ssl_ciph,ssl_stat,ssl_rsa,"+ -
"ssl_asn1,ssl_txt,ssl_algs,"+ -
"bio_ssl,ssl_err,kssl,tls_srp,t1_reneg"
"bio_ssl,ssl_err,kssl,tls_srp,t1_reneg,ssl_utst"
$!
$ COMPILEWITH_CC5 = ""
$!
@@ -240,7 +240,7 @@ $ NEXT_FILE:
$!
$! O.K, Extract The File Name From The File List.
$!
$ FILE_NAME = F$ELEMENT(FILE_COUNTER,",",LIB_SSL)
$ FILE_NAME = F$EDIT(F$ELEMENT(FILE_COUNTER,",",LIB_SSL),"COLLAPSE")
$!
$! Check To See If We Are At The End Of The File List.
$!
@@ -858,8 +858,11 @@ $ IF F$TYPE(USER_CCDEFS) .NES. "" THEN CCDEFS = CCDEFS + "," + USER_CCDEFS
$ CCEXTRAFLAGS = ""
$ IF F$TYPE(USER_CCFLAGS) .NES. "" THEN CCEXTRAFLAGS = USER_CCFLAGS
$ CCDISABLEWARNINGS = "" !!! "MAYLOSEDATA3" !!! "LONGLONGTYPE,LONGLONGSUFX,FOUNDCR"
$ IF F$TYPE(USER_CCDISABLEWARNINGS) .NES. "" THEN -
CCDISABLEWARNINGS = CCDISABLEWARNINGS + "," + USER_CCDISABLEWARNINGS
$ IF F$TYPE(USER_CCDISABLEWARNINGS) .NES. ""
$ THEN
$ IF CCDISABLEWARNINGS .NES. "" THEN CCDISABLEWARNINGS = CCDISABLEWARNINGS + ","
$ CCDISABLEWARNINGS = CCDISABLEWARNINGS + USER_CCDISABLEWARNINGS
$ ENDIF
$!
$! Check To See If We Have A ZLIB Option.
$!
@@ -653,6 +653,10 @@ struct ssl_session_st
*/
#define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020L
#define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040L
/* Send TLS_FALLBACK_SCSV in the ClientHello.
* To be set by applications that reconnect with a downgraded protocol
* version; see draft-ietf-tls-downgrade-scsv-00 for details. */
#define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080L

/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
* they cannot be used to clear bits. */
@@ -1511,6 +1515,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
#define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
#define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK /* fatal */

#define SSL_ERROR_NONE 0
#define SSL_ERROR_SSL 1
@@ -1621,6 +1626,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82
#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83

#define SSL_CTRL_CHECK_PROTO_VERSION 119

#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
#define DTLSv1_handle_timeout(ssl) \
@@ -2379,6 +2386,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_HTTPS_PROXY_REQUEST 155
#define SSL_R_HTTP_REQUEST 156
#define SSL_R_ILLEGAL_PADDING 283
#define SSL_R_INAPPROPRIATE_FALLBACK 373
#define SSL_R_INCONSISTENT_COMPRESSION 340
#define SSL_R_INVALID_CHALLENGE_LENGTH 158
#define SSL_R_INVALID_COMMAND 280
@@ -2525,6 +2533,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051
#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060
#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086
#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
@@ -128,9 +128,14 @@
extern "C" {
#endif

/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */
/* Signalling cipher suite value from RFC 5746
* (TLS_EMPTY_RENEGOTIATION_INFO_SCSV) */
#define SSL3_CK_SCSV 0x030000FF

/* Signalling cipher suite value from draft-ietf-tls-downgrade-scsv-00
* (TLS_FALLBACK_SCSV) */
#define SSL3_CK_FALLBACK_SCSV 0x03005600

#define SSL3_CK_RSA_NULL_MD5 0x03000001
#define SSL3_CK_RSA_NULL_SHA 0x03000002
#define SSL3_CK_RSA_RC4_40_MD5 0x03000003
@@ -383,6 +383,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST) ,"https proxy request"},
{ERR_REASON(SSL_R_HTTP_REQUEST) ,"http request"},
{ERR_REASON(SSL_R_ILLEGAL_PADDING) ,"illegal padding"},
{ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK),"inappropriate fallback"},
{ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"},
{ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},
{ERR_REASON(SSL_R_INVALID_COMMAND) ,"invalid command"},
@@ -529,6 +530,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),"tlsv1 alert decryption failed"},
{ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),"tlsv1 alert decrypt error"},
{ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),"tlsv1 alert export restriction"},
{ERR_REASON(SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK),"tlsv1 alert inappropriate fallback"},
{ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),"tlsv1 alert insufficient security"},
{ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),"tlsv1 alert internal error"},
{ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),"tlsv1 alert no renegotiation"},
@@ -1387,6 +1387,8 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,

if (sk == NULL) return(0);
q=p;
if (put_cb == NULL)
put_cb = s->method->put_cipher_by_char;

for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
{
@@ -1411,24 +1413,36 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
!(s->srp_ctx.srp_Mask & SSL_kSRP))
continue;
#endif /* OPENSSL_NO_SRP */
j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
j = put_cb(c,p);
p+=j;
}
/* If p == q, no ciphers and caller indicates an error. Otherwise
* add SCSV if not renegotiating.
*/
if (p != q && !s->renegotiate)
/* If p == q, no ciphers; caller indicates an error.
* Otherwise, add applicable SCSVs. */
if (p != q)
{
static SSL_CIPHER scsv =
if (!s->renegotiate)
{
0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);
p+=j;
static SSL_CIPHER scsv =
{
0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
j = put_cb(&scsv,p);
p+=j;
#ifdef OPENSSL_RI_DEBUG
fprintf(stderr, "SCSV sent by client\n");
fprintf(stderr, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV sent by client\n");
#endif
}
}

if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV)
{
static SSL_CIPHER scsv =
{
0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
j = put_cb(&scsv,p);
p+=j;
}
}

return(p-q);
}
@@ -1439,11 +1453,12 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
const SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *sk;
int i,n;

if (s->s3)
s->s3->send_connection_binding = 0;

n=ssl_put_cipher_by_char(s,NULL,NULL);
if ((num%n) != 0)
if (n == 0 || (num%n) != 0)
{
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
return(NULL);
@@ -1458,7 +1473,7 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,

for (i=0; i<num; i+=n)
{
/* Check for SCSV */
/* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */
if (s->s3 && (n != 3 || !p[0]) &&
(p[n-2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
(p[n-1] == (SSL3_CK_SCSV & 0xff)))
@@ -1478,6 +1493,23 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
continue;
}

/* Check for TLS_FALLBACK_SCSV */
if ((n != 3 || !p[0]) &&
(p[n-2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) &&
(p[n-1] == (SSL3_CK_FALLBACK_SCSV & 0xff)))
{
/* The SCSV indicates that the client previously tried a higher version.
* Fail if the current version is an unexpected downgrade. */
if (!SSL_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, 0, NULL))
{
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_INAPPROPRIATE_FALLBACK);
if (s->s3)
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INAPPROPRIATE_FALLBACK);
goto err;
}
continue;
}

c=ssl_get_cipher_by_char(s,p);
p+=n;
if (c != NULL)
@@ -2944,15 +2976,26 @@ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl)

SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx)
{
CERT *ocert = ssl->cert;
if (ssl->ctx == ctx)
return ssl->ctx;
#ifndef OPENSSL_NO_TLSEXT
if (ctx == NULL)
ctx = ssl->initial_ctx;
#endif
if (ssl->cert != NULL)
ssl_cert_free(ssl->cert);
ssl->cert = ssl_cert_dup(ctx->cert);
if (ocert != NULL)
{
int i;
/* Copy negotiated digests from original */
for (i = 0; i < SSL_PKEY_NUM; i++)
{
CERT_PKEY *cpk = ocert->pkeys + i;
CERT_PKEY *rpk = ssl->cert->pkeys + i;
rpk->digest = cpk->digest;
}
ssl_cert_free(ocert);
}
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
if (ssl->ctx != NULL)
SSL_CTX_free(ssl->ctx); /* decrement reference count */
@@ -1241,6 +1241,7 @@ int tls1_alert_code(int code)
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
case SSL_AD_INAPPROPRIATE_FALLBACK:return(TLS1_AD_INAPPROPRIATE_FALLBACK);
#if 0 /* not appropriate for TLS, not used for DTLS */
case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return
(DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
@@ -643,7 +643,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
#endif

#ifndef OPENSSL_NO_SRTP
if(SSL_get_srtp_profiles(s))
if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
{
int el;

@@ -806,7 +806,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
#endif

#ifndef OPENSSL_NO_SRTP
if(s->srtp_profile)
if(SSL_IS_DTLS(s) && s->srtp_profile)
{
int el;

@@ -1444,7 +1444,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in

/* session ticket processed earlier */
#ifndef OPENSSL_NO_SRTP
else if (type == TLSEXT_TYPE_use_srtp)
else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
&& type == TLSEXT_TYPE_use_srtp)
{
if(ssl_parse_clienthello_use_srtp_ext(s, data, size,
al))
@@ -1698,7 +1699,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
}
#endif
#ifndef OPENSSL_NO_SRTP
else if (type == TLSEXT_TYPE_use_srtp)
else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp)
{
if(ssl_parse_serverhello_use_srtp_ext(s, data, size,
al))
@@ -2347,7 +2348,10 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
HMAC_Final(&hctx, tick_hmac, NULL);
HMAC_CTX_cleanup(&hctx);
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen))
{
EVP_CIPHER_CTX_cleanup(&ctx);
return 2;
}
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
@@ -159,17 +159,19 @@ extern "C" {

#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0

#define TLS1_VERSION 0x0301
#define TLS1_1_VERSION 0x0302
#define TLS1_2_VERSION 0x0303
#define TLS1_2_VERSION_MAJOR 0x03
#define TLS1_2_VERSION_MINOR 0x03
#define TLS_MAX_VERSION TLS1_2_VERSION

#define TLS1_VERSION_MAJOR 0x03
#define TLS1_VERSION_MINOR 0x01

#define TLS1_1_VERSION 0x0302
#define TLS1_1_VERSION_MAJOR 0x03
#define TLS1_1_VERSION_MINOR 0x02

#define TLS1_VERSION 0x0301
#define TLS1_VERSION_MAJOR 0x03
#define TLS1_VERSION_MINOR 0x01
#define TLS1_2_VERSION_MAJOR 0x03
#define TLS1_2_VERSION_MINOR 0x03

#define TLS1_get_version(s) \
((s->version >> 8) == TLS1_VERSION_MAJOR ? s->version : 0)
@@ -187,6 +189,7 @@ extern "C" {
#define TLS1_AD_PROTOCOL_VERSION 70 /* fatal */
#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */
#define TLS1_AD_INTERNAL_ERROR 80 /* fatal */
#define TLS1_AD_INAPPROPRIATE_FALLBACK 86 /* fatal */
#define TLS1_AD_USER_CANCELLED 90
#define TLS1_AD_NO_RENEGOTIATION 100
/* codes 110-114 are from RFC3546 */
@@ -63,7 +63,8 @@ IGETEST= igetest
JPAKETEST= jpaketest
SRPTEST= srptest
ASN1TEST= asn1test
HEARTBEATTEST= heartbeat_test
HEARTBEATTEST= heartbeat_test
CONSTTIMETEST= constant_time_test

TESTS= alltests

@@ -75,7 +76,7 @@ EXE= $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT) $(ECDSATEST)$(EXE_EXT) $(ECDHTEST)
$(RANDTEST)$(EXE_EXT) $(DHTEST)$(EXE_EXT) $(ENGINETEST)$(EXE_EXT) \
$(BFTEST)$(EXE_EXT) $(CASTTEST)$(EXE_EXT) $(SSLTEST)$(EXE_EXT) $(EXPTEST)$(EXE_EXT) $(DSATEST)$(EXE_EXT) $(RSATEST)$(EXE_EXT) \
$(EVPTEST)$(EXE_EXT) $(IGETEST)$(EXE_EXT) $(JPAKETEST)$(EXE_EXT) $(SRPTEST)$(EXE_EXT) \
$(ASN1TEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT)
$(ASN1TEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT) $(CONSTTIMETEST)$(EXE_EXT)

# $(METHTEST)$(EXE_EXT)

@@ -87,7 +88,8 @@ OBJ= $(BNTEST).o $(ECTEST).o $(ECDSATEST).o $(ECDHTEST).o $(IDEATEST).o \
$(MDC2TEST).o $(RMDTEST).o \
$(RANDTEST).o $(DHTEST).o $(ENGINETEST).o $(CASTTEST).o \
$(BFTEST).o $(SSLTEST).o $(DSATEST).o $(EXPTEST).o $(RSATEST).o \
$(EVPTEST).o $(IGETEST).o $(JPAKETEST).o $(ASN1TEST).o $(HEARTBEATTEST).o
$(EVPTEST).o $(IGETEST).o $(JPAKETEST).o $(ASN1TEST).o \
$(HEARTBEATTEST).o $(CONSTTIMETEST).o

SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
$(MD2TEST).c $(MD4TEST).c $(MD5TEST).c \
@@ -97,7 +99,7 @@ SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
$(RANDTEST).c $(DHTEST).c $(ENGINETEST).c $(CASTTEST).c \
$(BFTEST).c $(SSLTEST).c $(DSATEST).c $(EXPTEST).c $(RSATEST).c \
$(EVPTEST).c $(IGETEST).c $(JPAKETEST).c $(SRPTEST).c $(ASN1TEST).c \
$(HEARTBEATTEST).c
$(HEARTBEATTEST).c $(CONSTTIMETEST).c

EXHEADER=
HEADER= $(EXHEADER)
@@ -140,7 +142,7 @@ alltests: \
test_enc test_x509 test_rsa test_crl test_sid \
test_gen test_req test_pkcs7 test_verify test_dh test_dsa \
test_ss test_ca test_engine test_evp test_ssl test_tsa test_ige \
test_jpake test_srp test_cms test_heartbeat
test_jpake test_srp test_cms test_heartbeat test_constant_time

test_evp:
../util/shlib_wrap.sh ./$(EVPTEST) evptests.txt
@@ -324,6 +326,10 @@ test_srp: $(SRPTEST)$(EXE_EXT)
test_heartbeat: $(HEARTBEATTEST)$(EXE_EXT)
../util/shlib_wrap.sh ./$(HEARTBEATTEST)

test_constant_time: $(CONSTTIMETEST)$(EXE_EXT)
@echo "Test constant time utilites"
../util/shlib_wrap.sh ./$(CONSTTIMETEST)

lint:
lint -DLINT $(INCLUDES) $(SRC)>fluff

@@ -485,6 +491,9 @@ $(SRPTEST)$(EXE_EXT): $(SRPTEST).o $(DLIBCRYPTO)
$(HEARTBEATTEST)$(EXE_EXT): $(HEARTBEATTEST).o $(DLIBCRYPTO)
@target=$(HEARTBEATTEST); $(BUILD_CMD_STATIC)

$(CONSTTIMETEST)$(EXE_EXT): $(CONSTTIMETEST).o
@target=$(CONSTTIMETEST) $(BUILD_CMD)

#$(AESTEST).o: $(AESTEST).c
# $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c

@@ -530,6 +539,9 @@ bntest.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
bntest.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h bntest.c
casttest.o: ../e_os.h ../include/openssl/cast.h ../include/openssl/e_os2.h
casttest.o: ../include/openssl/opensslconf.h casttest.c
constant_time_test.o: ../crypto/constant_time_locl.h ../e_os.h
constant_time_test.o: ../include/openssl/e_os2.h
constant_time_test.o: ../include/openssl/opensslconf.h constant_time_test.c
destest.o: ../include/openssl/des.h ../include/openssl/des_old.h
destest.o: ../include/openssl/e_os2.h ../include/openssl/opensslconf.h
destest.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
@@ -0,0 +1,330 @@
/* crypto/constant_time_test.c */
/*
* Utilities for constant-time cryptography.
*
* Author: Emilia Kasper (emilia@openssl.org)
* Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
* (Google).
* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/

#include "../crypto/constant_time_locl.h"

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
static const unsigned int CONSTTIME_FALSE = 0;
static const unsigned char CONSTTIME_TRUE_8 = 0xff;
static const unsigned char CONSTTIME_FALSE_8 = 0;

static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
const char* op_name, unsigned int a, unsigned int b, int is_true)
{
unsigned c = op(a, b);
if (is_true && c != CONSTTIME_TRUE)
{
fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
"(TRUE), got %du\n", op_name, a, b, CONSTTIME_TRUE, c);
return 1;
}
else if (!is_true && c != CONSTTIME_FALSE)
{
fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
"(FALSE), got %du\n", op_name, a, b, CONSTTIME_FALSE,
c);
return 1;
}
return 0;
}

static int test_binary_op_8(unsigned char (*op)(unsigned int a, unsigned int b),
const char* op_name, unsigned int a, unsigned int b, int is_true)
{
unsigned char c = op(a, b);
if (is_true && c != CONSTTIME_TRUE_8)
{
fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
"(TRUE), got %u\n", op_name, a, b, CONSTTIME_TRUE_8, c);
return 1;
}
else if (!is_true && c != CONSTTIME_FALSE_8)
{
fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
"(FALSE), got %u\n", op_name, a, b, CONSTTIME_FALSE_8,
c);
return 1;
}
return 0;
}

static int test_is_zero(unsigned int a)
{
unsigned int c = constant_time_is_zero(a);
if (a == 0 && c != CONSTTIME_TRUE)
{
fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
"expected %du (TRUE), got %du\n", a, CONSTTIME_TRUE, c);
return 1;
}
else if (a != 0 && c != CONSTTIME_FALSE)
{
fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
"expected %du (FALSE), got %du\n", a, CONSTTIME_FALSE,
c);
return 1;
}
return 0;
}

static int test_is_zero_8(unsigned int a)
{
unsigned char c = constant_time_is_zero_8(a);
if (a == 0 && c != CONSTTIME_TRUE_8)
{
fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
"expected %u (TRUE), got %u\n", a, CONSTTIME_TRUE_8, c);
return 1;
}
else if (a != 0 && c != CONSTTIME_FALSE)
{
fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
"expected %u (FALSE), got %u\n", a, CONSTTIME_FALSE_8,
c);
return 1;
}
return 0;
}

static int test_select(unsigned int a, unsigned int b)
{
unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
if (selected != a)
{
fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
"%du): expected %du(first value), got %du\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select(CONSTTIME_FALSE, a, b);
if (selected != b)
{
fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
"%du): expected %du(second value), got %du\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}

static int test_select_8(unsigned char a, unsigned char b)
{
unsigned char selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
if (selected != a)
{
fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
"%u): expected %u(first value), got %u\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
if (selected != b)
{
fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
"%u): expected %u(second value), got %u\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}

static int test_select_int(int a, int b)
{
int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
if (selected != a)
{
fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
"%d): expected %d(first value), got %d\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
if (selected != b)
{
fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
"%d): expected %d(second value), got %d\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}

static int test_eq_int(int a, int b)
{
unsigned int equal = constant_time_eq_int(a, b);
if (a == b && equal != CONSTTIME_TRUE)
{
fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
"expected %du(TRUE), got %du\n",
a, b, CONSTTIME_TRUE, equal);
return 1;
}
else if (a != b && equal != CONSTTIME_FALSE)
{
fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
"expected %du(FALSE), got %du\n",
a, b, CONSTTIME_FALSE, equal);
return 1;
}
return 0;
}

static int test_eq_int_8(int a, int b)
{
unsigned char equal = constant_time_eq_int_8(a, b);
if (a == b && equal != CONSTTIME_TRUE_8)
{
fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
"expected %u(TRUE), got %u\n",
a, b, CONSTTIME_TRUE_8, equal);
return 1;
}
else if (a != b && equal != CONSTTIME_FALSE_8)
{
fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
"expected %u(FALSE), got %u\n",
a, b, CONSTTIME_FALSE_8, equal);
return 1;
}
return 0;
}

static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX/2-1,
UINT_MAX/2, UINT_MAX/2+1, UINT_MAX-1,
UINT_MAX};

static unsigned char test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};

static int signed_test_values[] = {0, 1, -1, 1024, -1024, 12345, -12345,
32000, -32000, INT_MAX, INT_MIN, INT_MAX-1,
INT_MIN+1};


int main(int argc, char *argv[])
{
unsigned int a, b, i, j;
int c, d;
unsigned char e, f;
int num_failed = 0, num_all = 0;
fprintf(stdout, "Testing constant time operations...\n");

for (i = 0; i < sizeof(test_values)/sizeof(int); ++i)
{
a = test_values[i];
num_failed += test_is_zero(a);
num_failed += test_is_zero_8(a);
num_all += 2;
for (j = 0; j < sizeof(test_values)/sizeof(int); ++j)
{
b = test_values[j];
num_failed += test_binary_op(&constant_time_lt,
"constant_time_lt", a, b, a < b);
num_failed += test_binary_op_8(&constant_time_lt_8,
"constant_time_lt_8", a, b, a < b);
num_failed += test_binary_op(&constant_time_lt,
"constant_time_lt_8", b, a, b < a);
num_failed += test_binary_op_8(&constant_time_lt_8,
"constant_time_lt_8", b, a, b < a);
num_failed += test_binary_op(&constant_time_ge,
"constant_time_ge", a, b, a >= b);
num_failed += test_binary_op_8(&constant_time_ge_8,
"constant_time_ge_8", a, b, a >= b);
num_failed += test_binary_op(&constant_time_ge,
"constant_time_ge", b, a, b >= a);
num_failed += test_binary_op_8(&constant_time_ge_8,
"constant_time_ge_8", b, a, b >= a);
num_failed += test_binary_op(&constant_time_eq,
"constant_time_eq", a, b, a == b);
num_failed += test_binary_op_8(&constant_time_eq_8,
"constant_time_eq_8", a, b, a == b);
num_failed += test_binary_op(&constant_time_eq,
"constant_time_eq", b, a, b == a);
num_failed += test_binary_op_8(&constant_time_eq_8,
"constant_time_eq_8", b, a, b == a);
num_failed += test_select(a, b);
num_all += 13;
}
}

for (i = 0; i < sizeof(signed_test_values)/sizeof(int); ++i)
{
c = signed_test_values[i];
for (j = 0; j < sizeof(signed_test_values)/sizeof(int); ++j)
{
d = signed_test_values[j];
num_failed += test_select_int(c, d);
num_failed += test_eq_int(c, d);
num_failed += test_eq_int_8(c, d);
num_all += 3;
}
}

for (i = 0; i < sizeof(test_values_8); ++i)
{
e = test_values_8[i];
for (j = 0; j < sizeof(test_values_8); ++j)
{
f = test_values_8[j];
num_failed += test_select_8(e, f);
num_all += 1;
}
}

if (!num_failed)
{
fprintf(stdout, "ok (ran %d tests)\n", num_all);
return EXIT_SUCCESS;
}
else
{
fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
return EXIT_FAILURE;
}
}
@@ -251,14 +251,15 @@ static void group_order_tests(EC_GROUP *group)
if (!EC_POINT_is_at_infinity(group, Q)) ABORT;

/* Exercise EC_POINTs_mul, including corner cases. */
if (EC_POINT_is_at_infinity(group, P)) ABORT;
scalars[0] = n1; points[0] = Q; /* => infinity */
scalars[1] = n2; points[1] = P; /* => -P */
scalars[2] = n1; points[2] = Q; /* => infinity */
scalars[3] = n2; points[3] = Q; /* => infinity */
scalars[4] = n1; points[4] = P; /* => P */
scalars[5] = n2; points[5] = Q; /* => infinity */
if (!EC_POINTs_mul(group, Q, NULL, 5, points, scalars, ctx)) ABORT;
if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
if (!EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx)) ABORT;
if (!EC_POINT_is_at_infinity(group, P)) ABORT;
}
fprintf(stdout, "ok\n");

@@ -71,6 +71,43 @@

static const char rnd_seed[] = "string to make the random number generator think it has entropy";

/* test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */
static int test_exp_mod_zero() {
BIGNUM a, p, m;
BIGNUM r;
BN_CTX *ctx = BN_CTX_new();
int ret = 1;

BN_init(&m);
BN_one(&m);

BN_init(&a);
BN_one(&a);

BN_init(&p);
BN_zero(&p);

BN_init(&r);
BN_mod_exp(&r, &a, &p, &m, ctx);
BN_CTX_free(ctx);

if (BN_is_zero(&r))
ret = 0;
else
{
printf("1**0 mod 1 = ");
BN_print_fp(stdout, &r);
printf(", should be 0\n");
}

BN_free(&r);
BN_free(&a);
BN_free(&p);
BN_free(&m);

return ret;
}

int main(int argc, char *argv[])
{
BN_CTX *ctx;
@@ -190,7 +227,13 @@ int main(int argc, char *argv[])
ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks(out);
BIO_free(out);
printf(" done\n");
printf("\n");

if (test_exp_mod_zero() != 0)
goto err;

printf("done\n");

EXIT(0);
err:
ERR_load_crypto_strings();
@@ -6,6 +6,7 @@ $! A-Com Computing, Inc.
$! byer@mail.all-net.net
$!
$! Changes by Richard Levitte <richard@levitte.org>
$! Zoltan Arpadffy <arpadffy@polarhome.com>
$!
$! This command files compiles and creates all the various different
$! "test" programs for the different types of encryption for OpenSSL.
@@ -147,7 +148,7 @@ $ TEST_FILES = "BNTEST,ECTEST,ECDSATEST,ECDHTEST,IDEATEST,"+ -
"RANDTEST,DHTEST,ENGINETEST,"+ -
"BFTEST,CASTTEST,SSLTEST,EXPTEST,DSATEST,RSA_TEST,"+ -
"EVP_TEST,IGETEST,JPAKETEST,SRPTEST,"+ -
"ASN1TEST"
"ASN1TEST,HEARTBEAT_TEST,CONSTANT_TIME_TEST"
$! Should we add MTTEST,PQ_TEST,LH_TEST,DIVTEST,TABTEST as well?
$!
$! Additional directory information.
@@ -185,6 +186,8 @@ $ T_D_IGETEST := [-.test]
$ T_D_JPAKETEST := [-.crypto.jpake]
$ T_D_SRPTEST := [-.crypto.srp]
$ T_D_ASN1TEST := [-.test]
$ T_D_HEARTBEAT_TEST := [-.ssl]
$ T_D_CONSTANT_TIME_TEST := [-.crypto]
$!
$ TCPIP_PROGRAMS = ",,"
$ IF COMPILER .EQS. "VAXC" THEN -
@@ -56,7 +56,7 @@ $ tests := -
test_enc,test_x509,test_rsa,test_crl,test_sid,-
test_gen,test_req,test_pkcs7,test_verify,test_dh,test_dsa,-
test_ss,test_ca,test_engine,test_evp,test_ssl,test_tsa,test_ige,-
test_jpake,test_srp,test_cms
test_jpake,test_srp,test_cms,test_heartbeat,test_constant_time
$ endif
$ tests = f$edit(tests,"COLLAPSE")
$
@@ -95,6 +95,8 @@ $ IGETEST := igetest
$ JPAKETEST := jpaketest
$ SRPTEST := srptest
$ ASN1TEST := asn1test
$ HEARTBEATTEST := heartbeat_test
$ CONSTTIMETEST := constant_time_test
$!
$ tests_i = 0
$ loop_tests:
@@ -366,10 +368,20 @@ $ test_srp:
$ write sys$output "Test SRP"
$ mcr 'texe_dir''srptest'
$ return
$ test_heartbeat:
$ write sys$output "Test HEARTBEAT"
$ mcr 'texe_dir''heartbeattest'
$ return
$ test_constant_time:
$ write sys$output "Test constant time utilities"
$ mcr 'texe_dir''consttimetest'
$ return
$
$
$ exit:
$ on error then goto exit2 ! In case openssl.exe didn't build.
$ mcr 'exe_dir'openssl version -a
$ exit2:
$ set default '__save_default'
$ deassign sslroot
$ exit
@@ -173,6 +173,12 @@ else

echo test tls1 with SRP via BIO pair
$ssltest -bio_pair -tls1 -cipher SRP -srpuser test -srppass abc123

echo test tls1 with SRP auth
$ssltest -tls1 -cipher aSRP -srpuser test -srppass abc123

echo test tls1 with SRP auth via BIO pair
$ssltest -bio_pair -tls1 -cipher aSRP -srpuser test -srppass abc123
fi

exit 0
@@ -1145,6 +1145,7 @@ sub read_options
"dll" => \$shlib,
"shared" => 0,
"no-sctp" => 0,
"no-srtp" => 0,
"no-gmp" => 0,
"no-rfc3779" => 0,
"no-montasm" => 0,
@@ -117,6 +117,8 @@
"SSL_INTERN",
# SCTP
"SCTP",
# SRTP
"SRTP",
# Unit testing
"UNIT_TEST");

@@ -138,7 +140,7 @@
my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
my $no_jpake; my $no_srp; my $no_ssl2; my $no_ec2m; my $no_nistp_gcc;
my $no_nextprotoneg; my $no_sctp;
my $no_nextprotoneg; my $no_sctp; my $no_srtp;
my $no_unit_test;

my $fips;
@@ -238,6 +240,7 @@
elsif (/^no-jpake$/) { $no_jpake=1; }
elsif (/^no-srp$/) { $no_srp=1; }
elsif (/^no-sctp$/) { $no_sctp=1; }
elsif (/^no-srtp$/) { $no_srtp=1; }
elsif (/^no-unit-test$/){ $no_unit_test=1; }
}

@@ -1209,6 +1212,7 @@ sub is_valid
if ($keyword eq "JPAKE" && $no_jpake) { return 0; }
if ($keyword eq "SRP" && $no_srp) { return 0; }
if ($keyword eq "SCTP" && $no_sctp) { return 0; }
if ($keyword eq "SRTP" && $no_srtp) { return 0; }
if ($keyword eq "UNIT_TEST" && $no_unit_test) { return 0; }
if ($keyword eq "DEPRECATED" && $no_deprecated) { return 0; }

@@ -310,14 +310,14 @@ TLSv1_2_method 350 EXIST::FUNCTION:
SSL_SESSION_get_id_len 351 NOEXIST::FUNCTION:
kssl_ctx_get0_client_princ 352 EXIST::FUNCTION:KRB5
SSL_export_keying_material 353 EXIST::FUNCTION:TLSEXT
SSL_set_tlsext_use_srtp 354 EXIST::FUNCTION:
SSL_set_tlsext_use_srtp 354 EXIST::FUNCTION:SRTP
SSL_CTX_set_next_protos_advertised_cb 355 EXIST:!VMS:FUNCTION:NEXTPROTONEG
SSL_CTX_set_next_protos_adv_cb 355 EXIST:VMS:FUNCTION:NEXTPROTONEG
SSL_get0_next_proto_negotiated 356 EXIST::FUNCTION:NEXTPROTONEG
SSL_get_selected_srtp_profile 357 EXIST::FUNCTION:
SSL_CTX_set_tlsext_use_srtp 358 EXIST::FUNCTION:
SSL_get_selected_srtp_profile 357 EXIST::FUNCTION:SRTP
SSL_CTX_set_tlsext_use_srtp 358 EXIST::FUNCTION:SRTP
SSL_select_next_proto 359 EXIST::FUNCTION:NEXTPROTONEG
SSL_get_srtp_profiles 360 EXIST::FUNCTION:
SSL_get_srtp_profiles 360 EXIST::FUNCTION:SRTP
SSL_CTX_set_next_proto_select_cb 361 EXIST:!VMS:FUNCTION:NEXTPROTONEG
SSL_CTX_set_next_proto_sel_cb 361 EXIST:VMS:FUNCTION:NEXTPROTONEG
SSL_SESSION_get_compress_id 362 EXIST::FUNCTION:
@@ -95,29 +95,71 @@ Messages send by `.send(message, [sendHandle])` are obtained using the
* {Stream object}

A `Writable Stream` that represents the child process's `stdin`.
Closing this stream via `end()` often causes the child process to terminate.
If the child is waiting to read all its input, it will not continue until this
stream has been closed via `end()`.

If the child stdio streams are shared with the parent, then this will
If the child was not spawned with `stdio[0]` set to `'pipe'`, then this will
not be set.

`child.stdin` is shorthand for `child.stdio[0]`. Both properties will refer
to the same object, or null.

### child.stdout

* {Stream object}

A `Readable Stream` that represents the child process's `stdout`.

If the child stdio streams are shared with the parent, then this will
If the child was not spawned with `stdio[1]` set to `'pipe'`, then this will
not be set.

`child.stdout` is shorthand for `child.stdio[1]`. Both properties will refer
to the same object, or null.

### child.stderr

* {Stream object}

A `Readable Stream` that represents the child process's `stderr`.

If the child stdio streams are shared with the parent, then this will
If the child was not spawned with `stdio[2]` set to `'pipe'`, then this will
not be set.

`child.stderr` is shorthand for `child.stdio[2]`. Both properties will refer
to the same object, or null.

### child.stdio

* {Array}

A sparse array of pipes to the child process, corresponding with positions in
the [stdio](#child_process_options_stdio) option to
[spawn](#child_process_child_process_spawn_command_args_options) that have been
set to `'pipe'`.
Note that streams 0-2 are also available as ChildProcess.stdin,
ChildProcess.stdout, and ChildProcess.stderr, respectively.

In the following example, only the child's fd `1` is setup as a pipe, so only
the parent's `child.stdio[1]` is a stream, all other values in the array are
`null`.

child = child_process.spawn("ls", {
stdio: [
0, // use parents stdin for child
'pipe', // pipe child's stdout to parent
fs.openSync("err.out", "w") // direct child's stderr to a file
]
});

assert.equal(child.stdio[0], null);
assert.equal(child.stdio[0], child.stdin);

assert(child.stdout);
assert.equal(child.stdio[1], child.stdout);

assert.equal(child.stdio[2], null);
assert.equal(child.stdio[2], child.stderr);

### child.pid

* {Integer}
@@ -311,7 +353,12 @@ callback or returning an EventEmitter).
* `cwd` {String} Current working directory of the child process
* `stdio` {Array|String} Child's stdio configuration. (See below)
* `env` {Object} Environment key-value pairs
* `detached` {Boolean} The child will be a process group leader. (See below)
* `stdio` {Array|String} Child's stdio configuration. (See
[below](#child_process_options_stdio))
* `customFds` {Array} **Deprecated** File descriptors for the child to use
for stdio. (See [below](#child_process_options_customFds))
* `detached` {Boolean} The child will be a process group leader. (See
[below](#child_process_options_detached))
* `uid` {Number} Sets the user identity of the process. (See setuid(2).)
* `gid` {Number} Sets the group identity of the process. (See setgid(2).)
* return: {ChildProcess object}
@@ -325,8 +372,11 @@ The third argument is used to specify additional options, with these defaults:
env: process.env
}

`cwd` allows you to specify the working directory from which the process is spawned.
Use `env` to specify environment variables that will be visible to the new process.
Use `cwd` to specify the working directory from which the process is spawned.
If not given, the default is to inherit the current working directory.

Use `env` to specify environment variables that will be visible to the new
process, the default is `process.env`.

Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the exit code:

@@ -382,16 +432,16 @@ Example: A very elaborate way to run 'ps ax | grep ssh'
});


Example of checking for failed exec:
### options.stdio

var spawn = require('child_process').spawn,
child = spawn('bad_command');
As a shorthand, the `stdio` argument may also be one of the following
strings:

child.on('error', function (err) {
console.log('Failed to start child process.');
});
* `'pipe'` - `['pipe', 'pipe', 'pipe']`, this is the default value
* `'ignore'` - `['ignore', 'ignore', 'ignore']`
* `'inherit'` - `[process.stdin, process.stdout, process.stderr]` or `[0,1,2]`

The 'stdio' option to `child_process.spawn()` is an array where each
Otherwise, the 'stdio' option to `child_process.spawn()` is an array where each
index corresponds to a fd in the child. The value is one of the following:

1. `'pipe'` - Create a pipe between the child process and the parent process.
@@ -422,13 +472,6 @@ index corresponds to a fd in the child. The value is one of the following:
words, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the
default is `'ignore'`.

As a shorthand, the `stdio` argument may also be one of the following
strings, rather than an array:

* `ignore` - `['ignore', 'ignore', 'ignore']`
* `pipe` - `['pipe', 'pipe', 'pipe']`
* `inherit` - `[process.stdin, process.stdout, process.stderr]` or `[0,1,2]`

Example:

var spawn = require('child_process').spawn;
@@ -443,6 +486,8 @@ Example:
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

### options.detached

If the `detached` option is set, the child process will be made the leader of a
new process group. This makes it possible for the child to continue running
after the parent exits.
@@ -471,6 +516,15 @@ will not stay running in the background unless it is provided with a `stdio`
configuration that is not connected to the parent. If the parent's `stdio` is
inherited, the child will remain attached to the controlling terminal.

### options.customFds

There is a deprecated option called `customFds` which allows one to specify
specific file descriptors for the stdio of the child process. This API was
not portable to all platforms and therefore removed.
With `customFds` it was possible to hook up the new process' `[stdin, stdout,
stderr]` to existing streams; `-1` meant that a new stream should be created.
Use at your own risk.

See also: `child_process.exec()` and `child_process.fork()`

### child_process.exec(command[, options], callback)
@@ -562,7 +616,6 @@ leaner than `child_process.exec`. It has the same options.
* `options` {Object}
* `cwd` {String} Current working directory of the child process
* `env` {Object} Environment key-value pairs
* `encoding` {String} (Default: 'utf8')
* `execPath` {String} Executable used to create the child process
* `execArgv` {Array} List of string arguments passed to the executable
(Default: `process.execArgv`)
@@ -191,6 +191,16 @@ written data is used to compute the hash. Once the writable side of
the stream is ended, use the `read()` method to get the enciphered
contents. The legacy `update` and `final` methods are also supported.

Note: `createCipher` derives keys with the OpenSSL function [EVP_BytesToKey][]
with the digest algorithm set to MD5, one iteration, and no salt. The lack of
salt allows dictionary attacks as the same password always creates the same key.
The low iteration count and non-cryptographically secure hash algorithm allow
passwords to be tested very rapidly.

In line with OpenSSL's recommendation to use pbkdf2 instead of EVP_BytesToKey it
is recommended you derive a key and iv yourself with [crypto.pbkdf2][] and to
then use [createCipheriv()][] to create the cipher stream.

## crypto.createCipheriv(algorithm, key, iv)

Creates and returns a cipher object, with the given algorithm, key and
@@ -756,3 +766,5 @@ temporary measure.
[diffieHellman.setPublicKey()]: #crypto_diffiehellman_setpublickey_public_key_encoding
[RFC 2412]: http://www.rfc-editor.org/rfc/rfc2412.txt
[RFC 3526]: http://www.rfc-editor.org/rfc/rfc3526.txt
[crypto.pbkdf2]: #crypto_crypto_pbkdf2_password_salt_iterations_keylen_callback
[EVP_BytesToKey]: https://www.openssl.org/docs/crypto/EVP_BytesToKey.html
@@ -2,10 +2,13 @@

Stability: 3 - Stable

Use `require('dns')` to access this module. All methods in the dns module
use C-Ares except for `dns.lookup` which uses `getaddrinfo(3)` in a thread
pool. C-Ares is much faster than `getaddrinfo` but the system resolver is
more consistent with how other programs operate. When a user does
Use `require('dns')` to access this module. All methods in the dns module use
C-Ares except for `dns.lookup` which uses `getaddrinfo(3)` in a thread pool.
C-Ares is much faster than `getaddrinfo(3)` but, due to the way it is
configured by node, it doesn't use the same set of system configuration files.
For instance, _C- Ares will not use the configuration from `/etc/hosts`_. As a
result, __only `dns.lookup` should be expected to behave like other programs
running on the same system regarding name resolution.__ When a user does
`net.connect(80, 'google.com')` or `http.get({ host: 'google.com' })` the
`dns.lookup` method is used. Users who need to do a large number of lookups
quickly should use the methods that go through C-Ares.
@@ -134,8 +134,8 @@ The following options from [tls.connect()][] can also be specified. However, a
the list of supplied CAs. An `'error'` event is emitted if verification
fails. Verification happens at the connection level, *before* the HTTP
request is sent. Default `true`.
- `secureProtocol`: The SSL method to use, e.g. `SSLv3_method` to force
SSL version 3. The possible values depend on your installation of
- `secureProtocol`: The SSL method to use, e.g. `TLSv1_method` to force
TLS version 1. The possible values depend on your installation of
OpenSSL and are defined in the constant [SSL_METHODS][].

In order to specify these options, use a custom `Agent`.
@@ -33,9 +33,9 @@ on port 8124:

var net = require('net');
var server = net.createServer(function(c) { //'connection' listener
console.log('server connected');
console.log('client connected');
c.on('end', function() {
console.log('server disconnected');
console.log('client disconnected');
});
c.write('hello\r\n');
c.pipe(c);
@@ -98,15 +98,15 @@ Here is an example of a client of echo server as described previously:
var net = require('net');
var client = net.connect({port: 8124},
function() { //'connect' listener
console.log('client connected');
console.log('connected to server!');
client.write('world!\r\n');
});
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
client.on('end', function() {
console.log('client disconnected');
console.log('disconnected from server');
});

To connect on the socket `/tmp/echo.sock` the second line would just be
@@ -172,7 +172,7 @@ emulation with `process.kill()`, and `child_process.kill()`:

## process.stdout

A `Writable Stream` to `stdout`.
A `Writable Stream` to `stdout` (on fd `1`).

Example: the definition of `console.log`

@@ -207,7 +207,7 @@ See [the tty docs](tty.html#tty_tty) for more information.

## process.stderr

A writable stream to stderr.
A writable stream to stderr (on fd `2`).

`process.stderr` and `process.stdout` are unlike other streams in Node in
that they cannot be closed (`end()` will throw), they never emit the `finish`
@@ -222,7 +222,7 @@ event and that writes are usually blocking.

## process.stdin

A `Readable Stream` for stdin.
A `Readable Stream` for stdin (on fd `0`).

Example of opening standard input and listening for both events:

@@ -585,11 +585,10 @@ Calling [`write()`][] after calling [`end()`][] will raise an error.

```javascript
// write 'hello, ' and then end with 'world!'
http.createServer(function (req, res) {
res.write('hello, ');
res.end('world!');
// writing more now is not allowed!
});
var file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// writing more now is not allowed!
```

#### Event: 'finish'
@@ -1156,7 +1155,7 @@ initialized.
* `encoding` {String} If the chunk is a string, then this is the
encoding type. (Ignore if `decodeStrings` chunk is a buffer.)
* `callback` {Function} Call this function (optionally with an error
argument) when you are done processing the supplied chunk.
argument and data) when you are done processing the supplied chunk.

Note: **This function MUST NOT be called directly.** It should be
implemented by child classes, and called by the internal Transform
@@ -1176,7 +1175,20 @@ as a result of this chunk.

Call the callback function only when the current chunk is completely
consumed. Note that there may or may not be output as a result of any
particular input chunk.
particular input chunk. If you supply as the second argument to the
it will be passed to push method, in other words the following are
equivalent:

```javascript
transform.prototype._transform = function (data, encoding, callback) {
this.push(data);
callback();
}
transform.prototype._transform = function (data, encoding, callback) {
callback(null, data);
}
```

This method is prefixed with an underscore because it is internal to
the class that defines it, and should not be called directly by user
@@ -10,14 +10,14 @@ Secure Socket Layer: encrypted stream communication.
TLS/SSL is a public/private key infrastructure. Each client and each
server must have a private key. A private key is created like this:

openssl genrsa -out ryans-key.pem 1024
openssl genrsa -out ryans-key.pem 2048

All servers and some clients need to have a certificate. Certificates are public
keys signed by a Certificate Authority or self-signed. The first step to
getting a certificate is to create a "Certificate Signing Request" (CSR)
file. This is done with:

openssl req -new -key ryans-key.pem -out ryans-csr.pem
openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem

To create a self-signed certificate with the CSR, do this:

@@ -38,6 +38,40 @@ To create .pfx or .p12, do this:
- `certfile`: all CA certs concatenated in one file like
`cat ca1-cert.pem ca2-cert.pem > ca-cert.pem`

## Protocol support

Node.js is compiled with SSLv2 and SSLv3 protocol support by default, but these
protocols are **disabled**. They are considered insecure and could be easily
compromised as was shown by [CVE-2014-3566][]. However, in some situations, it
may cause problems with legacy clients/servers (such as Internet Explorer 6).
If you wish to enable SSLv2 or SSLv3, run node with the `--enable-ssl2` or
`--enable-ssl3` flag respectively. In future versions of Node.js SSLv2 and
SSLv3 will not be compiled in by default.

There is a way to force node into using SSLv3 or SSLv2 only mode by explicitly
specifying `secureProtocol` to `'SSLv3_method'` or `'SSLv2_method'`.

The default protocol method Node.js uses is `SSLv23_method` which would be more
accurately named `AutoNegotiate_method`. This method will try and negotiate
from the highest level down to whatever the client supports. To provide a
secure default, Node.js (since v0.10.33) explicitly disables the use of SSLv3
and SSLv2 by setting the `secureOptions` to be
`SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2` (again, unless you have passed
`--enable-ssl3`, or `--enable-ssl2`, or `SSLv3_method` as `secureProtocol`).

If you have set `secureOptions` to anything, we will not override your
options.

The ramifications of this behavior change:

* If your application is behaving as a secure server, clients who are `SSLv3`
only will now not be able to appropriately negotiate a connection and will be
refused. In this case your server will emit a `clientError` event. The error
message will include `'wrong version number'`.
* If your application is behaving as a secure client and communicating with a
server that doesn't support methods more secure than SSLv3 then your connection
won't be able to negotiate and will fail. In this case your client will emit a
an `error` event. The error message will include `'wrong version number'`.

## Client-initiated renegotiation attack mitigation

@@ -229,6 +263,10 @@ automatically set as a listener for the [secureConnection][] event. The
SSL version 3. The possible values depend on your installation of
OpenSSL and are defined in the constant [SSL_METHODS][].

- `secureOptions`: Set server options. For example, to disable the SSLv3
protocol set the `SSL_OP_NO_SSLv3` flag. See [SSL_CTX_set_options]
for all available options.

Here is a simple example echo server:

var tls = require('tls');
@@ -815,3 +853,4 @@ The numeric representation of the local port.
[ECDHE]: https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman
[asn1.js]: http://npmjs.org/package/asn1.js
[OCSP request]: http://en.wikipedia.org/wiki/OCSP_stapling
[CVE-2014-3566]: https://access.redhat.com/articles/1232123
@@ -82,6 +82,8 @@ Pass `true` as the third argument to treat `//foo/bar` as

Take a parsed URL object, and return a formatted URL string.

Here's how the formatting process works:

* `href` will be ignored.
* `protocol` is treated the same with or without the trailing `:` (colon).
* The protocols `http`, `https`, `ftp`, `gopher`, `file` will be
@@ -97,9 +99,9 @@ Take a parsed URL object, and return a formatted URL string.
* `host` will be used in place of `hostname` and `port`
* `pathname` is treated the same with or without the leading `/` (slash).
* `path` is treated the same with `pathname` but able to contain `query` as well.
* `search` will be used in place of `query`.
* `query` (object; see `querystring`) will only be used if `search` is absent.
* `search` is treated the same with or without the leading `?` (question mark).
* `search` will be used in place of `query`.
* It is treated the same with or without the leading `?` (question mark)
* `hash` is treated the same with or without the leading `#` (pound sign, anchor).

## url.resolve(from, to)
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Large diffs are not rendered by default.

@@ -62,6 +62,12 @@ and servers.

--max-stack-size=val set max v8 stack size (bytes)

--enable-ssl2 enable ssl2 in crypto, tls, and https
modules

--enable-ssl3 enable ssl3 in crypto, tls, and https
modules


.SH ENVIRONMENT VARIABLES

@@ -6,29 +6,34 @@
<link rel="stylesheet" href="assets/style.css">
<link rel="stylesheet" href="assets/sh.css">
<link rel="canonical" href="http://nodejs.org/api/__FILENAME__.html">
<script type="text/javascript" src="//use.typekit.net/mse5tqx.js"></script>
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
</head>
<body class="alt apidoc" id="api-section-__FILENAME__">
<div id="intro" class="interior">
<a href="/" title="Go back to the home page">
<img id="logo" src="http://nodejs.org/images/logo-light.png" alt="node.js">
</a>
<body class="alt apidoc int docs" id="docs">
<div id="nav">
<img id="logo" src="assets/logo.svg" alt="node.js">
<ul>
<li><a href="http://nodejs.org">Home</a></li>
<li><a href="http://nodejs.org/download/">Downloads</a></li>
<li class="active"><a href="http://nodejs.org/documentation/">Docs</a></li>
<li><a href="http://nodejs.org/community/">Community</a></li>
<li><a href="http://nodejs.org/about/">About</a></li>
<li><a href="http://jobs.nodejs.org">Jobs</a></li>
<li><a href="http://blog.nodejs.org">Blog</a></li>
</ul>
</div>
<div id="content-wrap">
<div id="content" class="clearfix">
<div id="column2" class="interior">
<ul>
<li><a href="/" class="home">Home</a></li>
<li><a href="/download/" class="download">Download</a></li>
<li><a href="/about/" class="about">About</a></li>
<li><a href="http://npmjs.org/" class="npm">npm Registry</a></li>
<li><a href="http://nodejs.org/api/" class="docs current">Docs</a></li>
<li><a href="http://blog.nodejs.org" class="blog">Blog</a></li>
<li><a href="/community/" class="community">Community</a></li>
<li><a href="/logos/" class="logos">Logos</a></li>
<li><a href="http://jobs.nodejs.org/" class="jobs">Jobs</a></li>
</ul>
<p class="twitter"><a href="http://twitter.com/nodejs">@nodejs</a></p>
</div>

<div id="column2" class="interior">
<!--<img src="/images/logo-light.svg" alt="node.js" width="170">-->
<ul class="docs-nav">
<li><a href="http://nodejs.org/documentation/">About Docs</a></li>
<li><a href="http://nodejs.org/documentation/tutorials/">Tutorials</a></li>
<li><a href="http://nodejs.org/documentation/contributing/">Contributing</a></li>
<li><a href="http://nodejs.org/documentation/localization/">Localization</a></li>
<li class="active"><a href="http://nodejs.org/api/">API Docs</a></li>
</ul>
</div>
<div id="column1" class="interior">
<header>
<h1>Node.js __VERSION__ Manual &amp; Documentation</h1>
@@ -52,26 +57,48 @@ <h2>Table of Contents</h2>
</div>
</div>
</div>
</div>
<div id="footer">
<a href="http://joyent.com" class="joyent-logo">Joyent</a>
<ul class="clearfix">
<li><a href="/">Node.js</a></li>
<li><a href="/download/">Download</a></li>
<li><a href="/about/">About</a></li>
<li><a href="http://npmjs.org/">npm Registry</a></li>
<li><a href="http://nodejs.org/api/">Docs</a></li>
<div class="foot-1">
<a href="http://www.joyent.com"><h5>The Node.js Project is Sponsored by</h5>
<img src="assets/joyent-footer.svg" width="200">
<p class="tag">Production Node +<br>High Performance Infrastructure</p></a>
<a href="https://my.joyent.com/landing/signup/701800000015696" class="button getstarted">Get Started</a>
</div>
<div class="foot-2">
<div class="foot-nav">
<ul>
<li><a href="http://nodejs.org/download/">Downloads</a></li>
</ul>
<ul>
<li><a href="http://nodejs.org/documentation/">Documentation</a></li>
<li><a href="http://nodejs.org/api/">API Docs</a></li>
<li><a href="http://nodejs.org/documentation/tutorials/">Tutorials</a></li>
<li><a href="http://nodejs.org/documentation/localization/">Localization</a></li>
</ul>
<ul>
<li><a href="http://nodejs.org/community/">Community</a></li>
<li><a href="https://github.com/joyent/node/issues">Github Issues</a></li>
<li><a href="http://groups.google.com/group/nodejs">Mailing List</a></li>
<li><a href="http://webchat.freenode.net/?channels=node.js">IRC</a></li>
<li><a href="https://twitter.com/nodejs">Twitter</a></li>
</ul>
<ul>
<li><a href="http://nodejs.org/about/">About</a></li>
<li><a href="http://nodejs.org/about/organization/">Organization</a></li>
<li><a href="http://nodejs.org/about/core-team/">Core Team</a></li>
<li><a href="http://nodejs.org/about/resources/">Resources</a></li>
</ul>
<ul>
<li><a href="http://blog.nodejs.org">Blog</a></li>
<li><a href="/community/">Community</a></li>
<li><a href="/logos/">Logos</a></li>
<li><a href="http://jobs.nodejs.org/">Jobs</a></li>
<li><a href="http://twitter.com/nodejs" class="twitter">@nodejs</a></li>
</ul>

<p>Copyright <a href="http://joyent.com/">Joyent, Inc</a>, Node.js is a <a href="/trademark-policy.pdf">trademark</a> of Joyent, Inc. View <a href="https://raw.github.com/joyent/node/__VERSION__/LICENSE">license</a>.</p>
</ul>
</div>
<p class="copyright">Copyright 2014 <a href="http://joyent.com/">Joyent, Inc</a>, Node.js is a <a href="https://nodejs.org/images/trademark-policy.pdf">trademark</a> of Joyent, Inc. <a href="https://raw.github.com/joyent/node/__VERSION__/LICENSE">View license</a>.</p>
</div>
</div>

<script src="../sh_main.js"></script>
<script src="../sh_javascript.min.js"></script>
<script src="/sh_main.js"></script>
<script src="/sh_javascript.min.js"></script>
<script>highlight(undefined, undefined, 'pre');</script>
<script>
window._gaq = [['_setAccount', 'UA-10874194-2'], ['_trackPageview']];
@@ -24,6 +24,7 @@ Readable.ReadableState = ReadableState;

var EE = require('events').EventEmitter;
var Stream = require('stream');
var Buffer = require('buffer').Buffer;
var util = require('util');
var StringDecoder;
var debug = util.debuglog('stream');
@@ -28,6 +28,7 @@ Writable.WritableState = WritableState;

var util = require('util');
var Stream = require('stream');
var Buffer = require('buffer').Buffer;

util.inherits(Writable, Stream);

@@ -560,6 +560,8 @@ exports.fork = function(modulePath /*, args, options*/) {
if (util.isArray(arguments[1])) {
args = arguments[1];
options = util._extend({}, arguments[2]);
} else if (arguments[1] && typeof arguments[1] !== 'object') {
throw new TypeError('Incorrect value of args option');
} else {
args = [];
options = util._extend({}, arguments[1]);
@@ -645,7 +647,7 @@ exports.exec = function(command /*, options, callback */) {


exports.execFile = function(file /* args, options, callback */) {
var args, callback;
var args = [], optionArg, callback;
var options = {
encoding: 'utf8',
timeout: 0,
@@ -655,18 +657,26 @@ exports.execFile = function(file /* args, options, callback */) {
env: null
};

// Parse the parameters.
// Parse the optional positional parameters.
var pos = 1;
if (pos < arguments.length && Array.isArray(arguments[pos])) {
args = arguments[pos++];
} else if (pos < arguments.length && arguments[pos] == null) {
pos++;
}

if (util.isFunction(arguments[arguments.length - 1])) {
callback = arguments[arguments.length - 1];
if (pos < arguments.length && typeof arguments[pos] === 'object') {
options = util._extend(options, arguments[pos++]);
} else if (pos < arguments.length && arguments[pos] == null) {
pos++;
}

if (util.isArray(arguments[1])) {
args = arguments[1];
options = util._extend(options, arguments[2]);
} else {
args = [];
options = util._extend(options, arguments[1]);
if (pos < arguments.length && typeof arguments[pos] === 'function') {
callback = arguments[pos++];
}

if (pos === 1 && arguments.length > 1) {
throw new TypeError('Incorrect value of args option');
}

var child = spawn(file, args, {
@@ -970,7 +980,7 @@ function normalizeSpawnArguments(file /*, args, options*/) {
}


var spawn = exports.spawn = function(/*file, args, options*/) {
var spawn = exports.spawn = function(file /*, args, options*/) {
var opts = normalizeSpawnArguments.apply(null, arguments);
var options = opts.options;
var child = new ChildProcess();
@@ -58,6 +58,127 @@ exports._toBuf = toBuf;
var assert = require('assert');
var StringDecoder = require('string_decoder').StringDecoder;

var CONTEXT_DEFAULT_OPTIONS = undefined;

function getSecureOptions(secureProtocol, secureOptions) {
if (CONTEXT_DEFAULT_OPTIONS === undefined) {
CONTEXT_DEFAULT_OPTIONS = 0;

if (!binding.SSL3_ENABLE)
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv3;

if (!binding.SSL2_ENABLE)
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv2;
}

if (secureOptions === undefined) {
if (secureProtocol === undefined ||
secureProtocol === 'SSLv23_method' ||
secureProtocol === 'SSLv23_server_method' ||
secureProtocol === 'SSLv23_client_method') {
secureOptions |= CONTEXT_DEFAULT_OPTIONS;
}
}

return secureOptions;
}
exports._getSecureOptions = getSecureOptions;


function Credentials(secureProtocol, flags, context) {
if (!(this instanceof Credentials)) {
return new Credentials(secureProtocol, flags, context);
}

if (!crypto) {
throw new Error('node.js not compiled with openssl crypto support.');
}

if (context) {
this.context = context;
} else {
this.context = new SecureContext();

if (secureProtocol) {
this.context.init(secureProtocol);
} else {
this.context.init();
}
}

flags = getSecureOptions(secureProtocol, flags);

this.context.setOptions(flags);
}

exports.Credentials = Credentials;


exports.createCredentials = function(options, context) {
if (!options) options = {};

var c = new Credentials(options.secureProtocol,
options.secureOptions,
context);

if (context) return c;

if (options.key) {
if (options.passphrase) {
c.context.setKey(options.key, options.passphrase);
} else {
c.context.setKey(options.key);
}
}

if (options.cert) c.context.setCert(options.cert);

if (options.ciphers) c.context.setCiphers(options.ciphers);

if (options.ca) {
if (Array.isArray(options.ca)) {
for (var i = 0, len = options.ca.length; i < len; i++) {
c.context.addCACert(options.ca[i]);
}
} else {
c.context.addCACert(options.ca);
}
} else {
c.context.addRootCerts();
}

if (options.crl) {
if (Array.isArray(options.crl)) {
for (var i = 0, len = options.crl.length; i < len; i++) {
c.context.addCRL(options.crl[i]);
}
} else {
c.context.addCRL(options.crl);
}
}

if (options.sessionIdContext) {
c.context.setSessionIdContext(options.sessionIdContext);
}

if (options.pfx) {
var pfx = options.pfx;
var passphrase = options.passphrase;

pfx = toBuf(pfx);
if (passphrase)
passphrase = toBuf(passphrase);

if (passphrase) {
c.context.loadPKCS12(pfx, passphrase);
} else {
c.context.loadPKCS12(pfx);
}
}

return c;
};


function LazyTransform(options) {
this._options = options;
@@ -23,6 +23,7 @@ var assert = require('assert');
var util = require('util');
var events = require('events');
var constants = require('constants');
var Buffer = require('buffer').Buffer;

var UDP = process.binding('udp_wrap').UDP;
var SendWrap = process.binding('udp_wrap').SendWrap;
@@ -31,6 +31,7 @@ var pathModule = require('path');
var binding = process.binding('fs');
var constants = process.binding('constants');
var fs = exports;
var Buffer = require('buffer').Buffer;
var Stream = require('stream').Stream;
var EventEmitter = require('events').EventEmitter;
var FSReqWrap = binding.FSReqWrap;
@@ -33,7 +33,7 @@ var PipeConnectWrap = process.binding('pipe_wrap').PipeConnectWrap;
var ShutdownWrap = process.binding('stream_wrap').ShutdownWrap;
var WriteWrap = process.binding('stream_wrap').WriteWrap;


var Buffer = require('buffer').Buffer;
var cluster;
var errnoException = util._errnoException;

@@ -284,6 +284,14 @@ var Timeout = function(after) {
this._repeat = false;
};


function unrefdHandle() {
this.owner._onTimeout();
if (!this.owner.repeat)
this.owner.close();
}


Timeout.prototype.unref = function() {
if (!this._handle) {
var now = Timer.now();
@@ -292,6 +300,7 @@ Timeout.prototype.unref = function() {
if (delay < 0) delay = 0;
exports.unenroll(this);
this._handle = new Timer();
this._handle.owner = this;
this._handle[kOnTimeout] = this._onTimeout;
this._handle.start(delay, 0);
this._handle.domain = this.domain;
@@ -22,6 +22,7 @@
var net = require('net');
var url = require('url');
var util = require('util');
var Buffer = require('buffer').Buffer;

// Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations
// every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more
@@ -23,6 +23,7 @@ var Transform = require('_stream_transform');

var binding = process.binding('zlib');
var util = require('util');
var Buffer = require('buffer').Buffer;
var assert = require('assert').ok;

// zlib doesn't provide these, so kludge them in following the same
@@ -2927,6 +2927,8 @@ static void PrintHelp() {
" present.\n"
#endif
#endif
" --enable-ssl2 enable ssl2\n"
" --enable-ssl3 enable ssl3\n"
"\n"
"Environment variables:\n"
#ifdef _WIN32
@@ -2994,6 +2996,12 @@ static void ParseArgs(int* argc,
} else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
printf("%s\n", NODE_VERSION);
exit(0);
} else if (strcmp(arg, "--enable-ssl2") == 0) {
SSL2_ENABLE = true;
argv[index] = const_cast<char*>("");
} else if (strcmp(arg, "--enable-ssl3") == 0) {
SSL3_ENABLE = true;
argv[index] = const_cast<char*>("");
} else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
PrintHelp();
exit(0);
@@ -74,6 +74,10 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
| XN_FLAG_FN_SN;

namespace node {

bool SSL2_ENABLE = false;
bool SSL3_ENABLE = false;

namespace crypto {

using v8::Array;
@@ -336,11 +340,23 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
return env->ThrowError("SSLv2 methods disabled");
#endif
} else if (strcmp(*sslmethod, "SSLv3_method") == 0) {
#ifndef OPENSSL_NO_SSL3
method = SSLv3_method();
#else
return env->ThrowError("SSLv3 methods disabled");
#endif
} else if (strcmp(*sslmethod, "SSLv3_server_method") == 0) {
#ifndef OPENSSL_NO_SSL3
method = SSLv3_server_method();
#else
return env->ThrowError("SSLv3 methods disabled");
#endif
} else if (strcmp(*sslmethod, "SSLv3_client_method") == 0) {
#ifndef OPENSSL_NO_SSL3
method = SSLv3_client_method();
#else
return env->ThrowError("SSLv3 methods disabled");
#endif
} else if (strcmp(*sslmethod, "SSLv23_method") == 0) {
method = SSLv23_method();
} else if (strcmp(*sslmethod, "SSLv23_server_method") == 0) {
@@ -789,7 +805,7 @@ void SecureContext::SetOptions(const FunctionCallbackInfo<Value>& args) {

SecureContext* sc = Unwrap<SecureContext>(args.Holder());

if (args.Length() != 1 || !args[0]->IntegerValue()) {
if (args.Length() != 1 && !args[0]->IsUint32()) {
return sc->env()->ThrowTypeError("Bad parameter");
}

@@ -60,6 +60,10 @@
#endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)

namespace node {

extern bool SSL2_ENABLE;
extern bool SSL3_ENABLE;

namespace crypto {

extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx);
@@ -1,6 +1,6 @@
/* tools/../src/node_root_certs.h -- Bundle of CA Root Certificates
*
* Certificate data from Mozilla as of: Sat Nov 9 22:37:55 2013
* Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012
*
* This is a bundle of X.509 certificates of public Certificate Authorities
* (CA). These were automatically extracted from Mozilla's root certificates
@@ -363,8 +363,9 @@ class ZCtx : public AsyncWrap {
ctx->MakeCallback(env->onerror_string(), ARRAY_SIZE(args), args);

// no hope of rescue.
if (ctx->write_in_progress_)
ctx->Unref();
ctx->write_in_progress_ = false;
ctx->Unref();
if (ctx->pending_close_)
ctx->Close();
}
@@ -298,3 +298,11 @@ exports.isValidHostname = function(str) {

return !!str.match(re) && str.length <= 255;
}

exports.hasMultiLocalhost = function hasMultiLocalhost() {
var TCP = process.binding('tcp_wrap').TCP;
var t = new TCP();
var ret = t.bind('127.0.0.2', exports.PORT);
t.close();
return ret === 0;
};
@@ -0,0 +1 @@
node_modules/
@@ -0,0 +1,15 @@
{
"name": "ssl-options-tests",
"version": "1.0.0",
"description": "",
"main": "test.js",
"scripts": {
"test": "node test.js"
},
"author": "",
"license": "MIT",
"dependencies": {
"async": "^0.9.0",
"debug": "^2.1.0"
}
}