int dtls1_send_hello_verify_request(SSL *s) { unsigned int len; unsigned char *buf; if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) { buf = (unsigned char *)s->init_buf->data; if (s->ctx->app_gen_cookie_cb == NULL || s->ctx->app_gen_cookie_cb(s, s->d1->cookie, &(s->d1->cookie_len)) == 0 || s->d1->cookie_len > 255) { SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); s->state = SSL_ST_ERR; return 0; } len = dtls1_raw_hello_verify_request(&buf[DTLS1_HM_HEADER_LENGTH], s->d1->cookie, s->d1->cookie_len); dtls1_set_message_header(s, buf, DTLS1_MT_HELLO_VERIFY_REQUEST, len, 0, len); len += DTLS1_HM_HEADER_LENGTH; s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B; /* number of bytes to write */ s->init_num = len; s->init_off = 0; } /* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); }
int dtls1_set_handshake_header(SSL *s, int htype, unsigned long len) { uint8_t *message = (uint8_t *)s->init_buf->data; const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; uint8_t serialised_header[DTLS1_HM_HEADER_LENGTH]; uint8_t *p = serialised_header; s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; s->d1->next_handshake_write_seq++; dtls1_set_message_header(s, htype, len, s->d1->handshake_write_seq, 0, len); s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH; s->init_off = 0; /* Buffer the message to handle re-xmits */ dtls1_buffer_message(s, 0); /* Add the new message to the handshake hash. Serialize the message * header as if it were a single fragment. */ *p++ = msg_hdr->type; l2n3(msg_hdr->msg_len, p); s2n(msg_hdr->seq, p); l2n3(0, p); l2n3(msg_hdr->msg_len, p); return ssl3_finish_mac(s, serialised_header, sizeof(serialised_header)) && ssl3_finish_mac(s, message + DTLS1_HM_HEADER_LENGTH, len); }
int dtls1_send_hello_verify_request(SSL *s) { unsigned int msg_len; unsigned char *msg, *buf, *p; if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) { buf = (unsigned char *)s->init_buf->data; msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]); /* Always use DTLS 1.0 version: see RFC 6347 */ *(p++) = DTLS1_VERSION >> 8; *(p++) = DTLS1_VERSION & 0xFF; if (s->ctx->app_gen_cookie_cb == NULL || s->ctx->app_gen_cookie_cb(s, s->d1->cookie, &(s->d1->cookie_len)) == 0) { OPENSSL_PUT_ERROR(SSL, dtls1_send_hello_verify_request, ERR_R_INTERNAL_ERROR); return 0; } *(p++) = (unsigned char) s->d1->cookie_len; memcpy(p, s->d1->cookie, s->d1->cookie_len); p += s->d1->cookie_len; msg_len = p - msg; dtls1_set_message_header(s, buf, DTLS1_MT_HELLO_VERIFY_REQUEST, msg_len, 0, msg_len); s->state=DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B; /* number of bytes to write */ s->init_num=p-buf; s->init_off=0; }
int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen) { unsigned char *p,*d; int i; unsigned long l; if (s->state == a) { d=(unsigned char *)s->init_buf->data; p= &(d[DTLS1_HM_HEADER_LENGTH]); i=s->method->ssl3_enc->final_finish_mac(s, &(s->s3->finish_dgst1), &(s->s3->finish_dgst2), sender,slen,s->s3->tmp.finish_md); s->s3->tmp.finish_md_len = i; memcpy(p, s->s3->tmp.finish_md, i); p+=i; l=i; /* Copy the finished so we can use it for * renegotiation checks */ if(s->type == SSL_ST_CONNECT) { OPENSSL_assert(i <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i); s->s3->previous_client_finished_len=i; } else { OPENSSL_assert(i <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i); s->s3->previous_server_finished_len=i; } #ifdef OPENSSL_SYS_WIN16 /* MSVC 1.5 does not clear the top bytes of the word unless * I do this. */ l&=0xffff; #endif d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l); s->init_num=(int)l+DTLS1_HM_HEADER_LENGTH; s->init_off=0; /* buffer the message to handle re-xmits */ dtls1_buffer_message(s, 0); s->state=b; } /* SSL3_ST_SEND_xxxxxx_HELLO_B */ return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); }
unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; int i; unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; BUF_MEM *buf; /* TLSv1 sends a chain with nothing in it, instead of an alert */ buf=s->init_buf; if (!BUF_MEM_grow_clean(buf,10)) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } if (x != NULL) { X509_STORE_CTX xs_ctx; if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); return(0); } X509_verify_cert(&xs_ctx); /* Don't leave errors in the queue */ ERR_clear_error(); for (i=0; i < sk_X509_num(xs_ctx.chain); i++) { x = sk_X509_value(xs_ctx.chain, i); if (!dtls1_add_cert_to_buf(buf, &l, x)) { X509_STORE_CTX_cleanup(&xs_ctx); return 0; } } X509_STORE_CTX_cleanup(&xs_ctx); } /* Thawte special :-) */ for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++) { x=sk_X509_value(s->ctx->extra_certs,i); if (!dtls1_add_cert_to_buf(buf, &l, x)) return 0; } l-= (3 + DTLS1_HM_HEADER_LENGTH); p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); l2n3(l,p); l+=3; p=(unsigned char *)&(buf->data[0]); p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l); l+=DTLS1_HM_HEADER_LENGTH; return(l); }
static void dtls1_set_handshake_header(SSL *s, int htype, unsigned long len) { unsigned char *p = (unsigned char *)s->init_buf->data; dtls1_set_message_header(s, p, htype, len, 0, len); s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH; s->init_off = 0; /* Buffer the message to handle re-xmits */ dtls1_buffer_message(s, 0); }
int dtls1_send_hello_request(SSL *s) { unsigned char *p; if (s->state == SSL3_ST_SW_HELLO_REQ_A) { p=(unsigned char *)s->init_buf->data; p = dtls1_set_message_header(s, p, SSL3_MT_HELLO_REQUEST, 0, 0, 0); s->state=SSL3_ST_SW_HELLO_REQ_B; /* number of bytes to write */ s->init_num=DTLS1_HM_HEADER_LENGTH; s->init_off=0; /* no need to buffer this message, since there are no retransmit * requests for it */ } /* SSL3_ST_SW_HELLO_REQ_B */ return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); }
int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen) { unsigned char *p,*d; int i; unsigned long l; if (s->state == a) { d=(unsigned char *)s->init_buf->data; p= &(d[DTLS1_HM_HEADER_LENGTH]); i=s->method->ssl3_enc->final_finish_mac(s, &(s->s3->finish_dgst1), &(s->s3->finish_dgst2), sender,slen,s->s3->tmp.finish_md); s->s3->tmp.finish_md_len = i; memcpy(p, s->s3->tmp.finish_md, i); p+=i; l=i; #ifdef OPENSSL_SYS_WIN16 /* MSVC 1.5 does not clear the top bytes of the word unless * I do this. */ l&=0xffff; #endif d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l); s->init_num=(int)l+DTLS1_HM_HEADER_LENGTH; s->init_off=0; /* buffer the message to handle re-xmits */ dtls1_buffer_message(s, 0); s->state=b; } /* SSL3_ST_SEND_xxxxxx_HELLO_B */ return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); }
int dtls1_send_hello_verify_request(SSL *s) { unsigned int msg_len; unsigned char *msg, *buf, *p; if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) { buf = (unsigned char *)s->init_buf->data; msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]); *(p++) = s->version >> 8; *(p++) = s->version & 0xFF; *(p++) = (unsigned char) s->d1->cookie_len; if ( s->ctx->app_gen_cookie_cb != NULL && s->ctx->app_gen_cookie_cb(s, s->d1->cookie, &(s->d1->cookie_len)) == 0) { SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,ERR_R_INTERNAL_ERROR); return 0; } /* else the cookie is assumed to have * been initialized by the application */ memcpy(p, s->d1->cookie, s->d1->cookie_len); p += s->d1->cookie_len; msg_len = p - msg; dtls1_set_message_header(s, buf, DTLS1_MT_HELLO_VERIFY_REQUEST, msg_len, 0, msg_len); s->state=DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B; /* number of bytes to write */ s->init_num=p-buf; s->init_off=0; /* buffer the message to handle re-xmits */ dtls1_buffer_message(s, 0); }
int dtls1_client_hello(SSL *s) { unsigned char *buf; unsigned char *p, *d; unsigned int i; unsigned long l; buf = (unsigned char *)s->init_buf->data; if (s->state == SSL3_ST_CW_CLNT_HELLO_A) { SSL_SESSION *sess = s->session; if ((s->session == NULL) || (s->session->ssl_version != s->version) || (!sess->session_id_length && !sess->tlsext_tick) || (s->session->not_resumable)) { if (!ssl_get_new_session(s, 0)) goto err; } /* else use the pre-loaded session */ p = s->s3->client_random; /* if client_random is initialized, reuse it, we are * required to use same upon reply to HelloVerify */ for (i = 0; p[i]=='\0' && i < sizeof(s->s3->client_random); i++) ; if (i == sizeof(s->s3->client_random)) RAND_pseudo_bytes(p, sizeof(s->s3->client_random)); /* Do the message type and length last */ d = p = &(buf[DTLS1_HM_HEADER_LENGTH]); *(p++) = s->version >> 8; *(p++) = s->version&0xff; s->client_version = s->version; /* Random stuff */ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); p += SSL3_RANDOM_SIZE; /* Session ID */ if (s->new_session) i = 0; else i = s->session->session_id_length; *(p++) = i; if (i != 0) { if (i > sizeof s->session->session_id) { SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); goto err; } memcpy(p, s->session->session_id, i); p += i; } /* cookie stuff */ if (s->d1->cookie_len > sizeof(s->d1->cookie)) { SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); goto err; } *(p++) = s->d1->cookie_len; memcpy(p, s->d1->cookie, s->d1->cookie_len); p += s->d1->cookie_len; /* Ciphers supported */ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]), 0); if (i == 0) { SSLerr(SSL_F_DTLS1_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE); goto err; } s2n(i, p); p += i; /* add in (no) COMPRESSION */ *(p++) = 1; *(p++) = 0; /* Add the NULL method */ if ((p = ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) { SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); goto err; } l = (p - d); d = buf; d = dtls1_set_message_header(s, d, SSL3_MT_CLIENT_HELLO, l, 0, l); s->state = SSL3_ST_CW_CLNT_HELLO_B; /* number of bytes to write */ s->init_num = p - buf; s->init_off = 0; /* buffer the message to handle re-xmits */ dtls1_buffer_message(s, 0); }
unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; int n,i; unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; BUF_MEM *buf; X509_STORE_CTX xs_ctx; X509_OBJECT obj; /* TLSv1 sends a chain with nothing in it, instead of an alert */ buf=s->init_buf; if (!BUF_MEM_grow_clean(buf,10)) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } if (x != NULL) { if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL)) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); return(0); } for (;;) { n=i2d_X509(x,NULL); if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } p=(unsigned char *)&(buf->data[l]); l2n3(n,p); i2d_X509(x,&p); l+=n+3; if (X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)) == 0) break; i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509, X509_get_issuer_name(x),&obj); if (i <= 0) break; x=obj.data.x509; /* Count is one too high since the X509_STORE_get uped the * ref count */ X509_free(x); } X509_STORE_CTX_cleanup(&xs_ctx); } /* Thawte special :-) */ if (s->ctx->extra_certs != NULL) for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++) { x=sk_X509_value(s->ctx->extra_certs,i); n=i2d_X509(x,NULL); if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } p=(unsigned char *)&(buf->data[l]); l2n3(n,p); i2d_X509(x,&p); l+=n+3; } l-= (3 + DTLS1_HM_HEADER_LENGTH); p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); l2n3(l,p); l+=3; p=(unsigned char *)&(buf->data[0]); p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l); l+=DTLS1_HM_HEADER_LENGTH; return(l); }