/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. * It does not contain branches that may leak sensitive information. */ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; BIGNUM local_A, local_B; BIGNUM *pA, *pB; BIGNUM *ret = NULL; int sign; BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) { goto err; } if (out == NULL) { R = BN_new(); } else { R = out; } if (R == NULL) { goto err; } BN_zero(Y); if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) { goto err; } A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pB = &local_B; BN_with_flags(pB, B, BN_FLG_CONSTTIME); if (!BN_nnmod(B, pB, A, ctx)) { goto err; } } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pA = &local_A; BN_with_flags(pA, A, BN_FLG_CONSTTIME); /* (D, M) := (A/B, A%B) ... */ if (!BN_div(D, M, pA, B, ctx)) { goto err; } /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp = A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A = B; B = M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ if (!BN_mul(tmp, D, X, ctx)) { goto err; } if (!BN_add(tmp, tmp, Y)) { goto err; } M = Y; /* keep the BIGNUM object, the value does not matter */ Y = X; X = tmp; sign = -sign; } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y, n, Y)) { goto err; } } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y, n) < 0) { if (!BN_copy(R, Y)) { goto err; } } else { if (!BN_nnmod(R, Y, n, ctx)) { goto err; } } } else { OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); goto err; } ret = R; err: if (ret == NULL && out == NULL) { BN_free(R); } BN_CTX_end(ctx); return ret; }
int dtls1_connect(SSL *s) { BUF_MEM *buf = NULL; void (*cb)(const SSL *ssl, int type, int val) = NULL; int ret = -1; int new_state, state, skip = 0; assert(s->handshake_func == dtls1_connect); assert(!s->server); assert(SSL_IS_DTLS(s)); ERR_clear_error(); ERR_clear_system_error(); if (s->info_callback != NULL) { cb = s->info_callback; } else if (s->ctx->info_callback != NULL) { cb = s->ctx->info_callback; } s->in_handshake++; for (;;) { state = s->state; switch (s->state) { case SSL_ST_CONNECT: if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_START, 1); } if (s->init_buf == NULL) { buf = BUF_MEM_new(); if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; goto end; } s->init_buf = buf; buf = NULL; } if (!ssl_init_wbio_buffer(s, 0)) { ret = -1; goto end; } /* don't push the buffering BIO quite yet */ s->state = SSL3_ST_CW_CLNT_HELLO_A; s->init_num = 0; s->d1->send_cookie = 0; s->hit = 0; break; case SSL3_ST_CW_CLNT_HELLO_A: case SSL3_ST_CW_CLNT_HELLO_B: s->shutdown = 0; /* every DTLS ClientHello resets Finished MAC */ if (!ssl3_init_finished_mac(s)) { OPENSSL_PUT_ERROR(SSL, dtls1_connect, ERR_R_INTERNAL_ERROR); ret = -1; goto end; } dtls1_start_timer(s); ret = ssl3_send_client_hello(s); if (ret <= 0) { goto end; } if (s->d1->send_cookie) { s->state = SSL3_ST_CW_FLUSH; s->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A; } else { s->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; } s->init_num = 0; /* turn on buffering for the next lot of output */ if (s->bbio != s->wbio) { s->wbio = BIO_push(s->bbio, s->wbio); } break; case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: ret = dtls1_get_hello_verify(s); if (ret <= 0) { goto end; } if (s->d1->send_cookie) { /* start again, with a cookie */ dtls1_stop_timer(s); s->state = SSL3_ST_CW_CLNT_HELLO_A; } else { s->state = SSL3_ST_CR_SRVR_HELLO_A; } s->init_num = 0; break; case SSL3_ST_CR_SRVR_HELLO_A: case SSL3_ST_CR_SRVR_HELLO_B: ret = ssl3_get_server_hello(s); if (ret <= 0) { goto end; } if (s->hit) { s->state = SSL3_ST_CR_FINISHED_A; if (s->tlsext_ticket_expected) { /* receive renewed session ticket */ s->state = SSL3_ST_CR_SESSION_TICKET_A; } } else { s->state = SSL3_ST_CR_CERT_A; } s->init_num = 0; break; case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { ret = ssl3_get_server_certificate(s); if (ret <= 0) { goto end; } if (s->s3->tmp.certificate_status_expected) { s->state = SSL3_ST_CR_CERT_STATUS_A; } else { s->state = SSL3_ST_CR_KEY_EXCH_A; } } else { skip = 1; s->state = SSL3_ST_CR_KEY_EXCH_A; } s->init_num = 0; break; case SSL3_ST_CR_KEY_EXCH_A: case SSL3_ST_CR_KEY_EXCH_B: ret = ssl3_get_server_key_exchange(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_CERT_REQ_A; s->init_num = 0; break; case SSL3_ST_CR_CERT_REQ_A: case SSL3_ST_CR_CERT_REQ_B: ret = ssl3_get_certificate_request(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_SRVR_DONE_A; s->init_num = 0; break; case SSL3_ST_CR_SRVR_DONE_A: case SSL3_ST_CR_SRVR_DONE_B: ret = ssl3_get_server_done(s); if (ret <= 0) { goto end; } dtls1_stop_timer(s); if (s->s3->tmp.cert_req) { s->s3->tmp.next_state = SSL3_ST_CW_CERT_A; } else { s->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A; } s->init_num = 0; s->state = s->s3->tmp.next_state; break; case SSL3_ST_CW_CERT_A: case SSL3_ST_CW_CERT_B: case SSL3_ST_CW_CERT_C: case SSL3_ST_CW_CERT_D: dtls1_start_timer(s); ret = ssl3_send_client_certificate(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_KEY_EXCH_A; s->init_num = 0; break; case SSL3_ST_CW_KEY_EXCH_A: case SSL3_ST_CW_KEY_EXCH_B: dtls1_start_timer(s); ret = ssl3_send_client_key_exchange(s); if (ret <= 0) { goto end; } /* For TLS, cert_req is set to 2, so a cert chain * of nothing is sent, but no verify packet is sent */ if (s->s3->tmp.cert_req == 1) { s->state = SSL3_ST_CW_CERT_VRFY_A; } else { s->state = SSL3_ST_CW_CHANGE_A; s->s3->change_cipher_spec = 0; } s->init_num = 0; break; case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: dtls1_start_timer(s); ret = ssl3_send_cert_verify(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_CHANGE_A; s->init_num = 0; s->s3->change_cipher_spec = 0; break; case SSL3_ST_CW_CHANGE_A: case SSL3_ST_CW_CHANGE_B: if (!s->hit) { dtls1_start_timer(s); } ret = dtls1_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A, SSL3_ST_CW_CHANGE_B); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_FINISHED_A; s->init_num = 0; s->session->cipher = s->s3->tmp.new_cipher; if (!s->enc_method->setup_key_block(s) || !s->enc_method->change_cipher_state( s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { ret = -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_CW_FINISHED_A: case SSL3_ST_CW_FINISHED_B: if (!s->hit) { dtls1_start_timer(s); } ret = ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B, s->enc_method->client_finished_label, s->enc_method->client_finished_label_len); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_FLUSH; if (s->hit) { s->s3->tmp.next_state = SSL_ST_OK; } else { /* Allow NewSessionTicket if ticket expected */ if (s->tlsext_ticket_expected) { s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A; } else { s->s3->tmp.next_state = SSL3_ST_CR_FINISHED_A; } } s->init_num = 0; break; case SSL3_ST_CR_SESSION_TICKET_A: case SSL3_ST_CR_SESSION_TICKET_B: ret = ssl3_get_new_session_ticket(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_FINISHED_A; s->init_num = 0; break; case SSL3_ST_CR_CERT_STATUS_A: case SSL3_ST_CR_CERT_STATUS_B: ret = ssl3_get_cert_status(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_KEY_EXCH_A; s->init_num = 0; break; case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) { goto end; } dtls1_stop_timer(s); if (s->hit) { s->state = SSL3_ST_CW_CHANGE_A; } else { s->state = SSL_ST_OK; } s->init_num = 0; break; case SSL3_ST_CW_FLUSH: s->rwstate = SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { ret = -1; goto end; } s->rwstate = SSL_NOTHING; s->state = s->s3->tmp.next_state; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); /* Remove write buffering now. */ ssl_free_wbio_buffer(s); s->init_num = 0; s->s3->initial_handshake_complete = 1; ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); ret = 1; if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_DONE, 1); } /* done with handshaking */ s->d1->handshake_read_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; default: OPENSSL_PUT_ERROR(SSL, dtls1_connect, SSL_R_UNKNOWN_STATE); ret = -1; goto end; } /* did we do anything? */ if (!s->s3->tmp.reuse_message && !skip) { if ((cb != NULL) && (s->state != state)) { new_state = s->state; s->state = state; cb(s, SSL_CB_CONNECT_LOOP, 1); s->state = new_state; } } skip = 0; } end: s->in_handshake--; BUF_MEM_free(buf); if (cb != NULL) { cb(s, SSL_CB_CONNECT_EXIT, ret); } return ret; }
static int bio_write(BIO *bio, const char *buf, int num_) { size_t num = num_; size_t rest; struct bio_bio_st *b; BIO_clear_retry_flags(bio); if (!bio->init || buf == NULL || num == 0) { return 0; } b = bio->ptr; assert(b != NULL); assert(b->peer != NULL); assert(b->buf != NULL); b->request = 0; if (b->closed) { // we already closed OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); return -1; } assert(b->len <= b->size); if (b->len == b->size) { BIO_set_retry_write(bio); // buffer is full return -1; } // we can write if (num > b->size - b->len) { num = b->size - b->len; } // now write "num" bytes rest = num; assert(rest > 0); // one or two iterations do { size_t write_offset; size_t chunk; assert(b->len + rest <= b->size); write_offset = b->offset + b->len; if (write_offset >= b->size) { write_offset -= b->size; } // b->buf[write_offset] is the first byte we can write to. if (write_offset + rest <= b->size) { chunk = rest; } else { // wrap around ring buffer chunk = b->size - write_offset; } OPENSSL_memcpy(b->buf + write_offset, buf, chunk); b->len += chunk; assert(b->len <= b->size); rest -= chunk; buf += chunk; } while (rest); return num; }
static int aead_rc4_md5_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len, const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad, size_t ad_len) { struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state; MD5_CTX md; #if defined(STITCHED_CALL) size_t rc4_off, md5_off, blocks; extern unsigned int OPENSSL_ia32cap_P[]; #else const size_t rc4_off = 0; const size_t md5_off = 0; #endif uint8_t digest[MD5_DIGEST_LENGTH]; if (in_len + rc4_ctx->tag_len < in_len) { OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_TOO_LARGE); return 0; } if (nonce_len != 0) { OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_IV_TOO_LARGE); return 0; } if (max_out_len < in_len + rc4_ctx->tag_len) { OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_BUFFER_TOO_SMALL); return 0; } if (nonce_len != 0) { OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_TOO_LARGE); return 0; } memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX)); /* The MAC's payload begins with the additional data. See * https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */ MD5_Update(&md, ad, ad_len); #if defined(STITCHED_CALL) /* 32 is $MOD from rc4_md5-x86_64.pl. */ rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1)); md5_off = MD5_CBLOCK - md.num; /* Ensure RC4 is behind MD5. */ if (rc4_off > md5_off) { md5_off += MD5_CBLOCK; } assert(md5_off >= rc4_off); if (in_len > md5_off && (blocks = (in_len - md5_off) / MD5_CBLOCK) && (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) { /* Process the initial portions of the plaintext normally. */ MD5_Update(&md, in, md5_off); RC4(&rc4_ctx->rc4, rc4_off, in, out); /* Process the next |blocks| blocks of plaintext with stitched routines. */ rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, in + md5_off, blocks); blocks *= MD5_CBLOCK; rc4_off += blocks; md5_off += blocks; md.Nh += blocks >> 29; md.Nl += blocks <<= 3; if (md.Nl < (unsigned int)blocks) { md.Nh++; } } else {
/* Obtain handshake message of message type |msg_type| (any if |msg_type| == -1), * maximum acceptable body length |max|. The first four bytes (msg_type and * length) are read in state |header_state|, the body is read in state |body_state|. */ long ssl3_get_message(SSL *s, int header_state, int body_state, int msg_type, long max, enum ssl_hash_message_t hash_message, int *ok) { uint8_t *p; unsigned long l; long n; int al; if (s->s3->tmp.reuse_message) { /* A ssl_dont_hash_message call cannot be combined with reuse_message; the * ssl_dont_hash_message would have to have been applied to the previous * call. */ assert(hash_message == ssl_hash_message); s->s3->tmp.reuse_message = 0; if (msg_type >= 0 && s->s3->tmp.message_type != msg_type) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } *ok = 1; s->state = body_state; s->init_msg = (uint8_t *)s->init_buf->data + 4; s->init_num = (int)s->s3->tmp.message_size; return s->init_num; } p = (uint8_t *)s->init_buf->data; if (s->state == header_state) { assert(s->init_num < 4); for (;;) { while (s->init_num < 4) { int bytes_read = ssl3_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->init_num], 4 - s->init_num, 0); if (bytes_read <= 0) { *ok = 0; return bytes_read; } s->init_num += bytes_read; } static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0}; if (s->server || memcmp(p, kHelloRequest, sizeof(kHelloRequest)) != 0) { break; } /* The server may always send 'Hello Request' messages -- we are doing * a handshake anyway now, so ignore them if their format is correct. * Does not count for 'Finished' MAC. */ s->init_num = 0; if (s->msg_callback) { s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s, s->msg_callback_arg); } } /* s->init_num == 4 */ if (msg_type >= 0 && *p != msg_type) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } s->s3->tmp.message_type = *(p++); n2l3(p, l); if (l > (unsigned long)max) { al = SSL_AD_ILLEGAL_PARAMETER; OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } if (l && !BUF_MEM_grow_clean(s->init_buf, l + 4)) { OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); goto err; } s->s3->tmp.message_size = l; s->state = body_state; s->init_msg = (uint8_t *)s->init_buf->data + 4; s->init_num = 0; } /* next state (body_state) */ p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { int bytes_read = ssl3_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->init_num], n, 0); if (bytes_read <= 0) { s->rwstate = SSL_READING; *ok = 0; return bytes_read; } s->init_num += bytes_read; n -= bytes_read; } /* Feed this message into MAC computation. */ if (hash_message == ssl_hash_message && !ssl3_hash_current_message(s)) { goto err; } if (s->msg_callback) { s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg); } *ok = 1; return s->init_num; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: *ok = 0; return -1; }
static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len, const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad, size_t ad_len) { AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)&ctx->state; if (tls_ctx->cipher_ctx.encrypt) { // Unlike a normal AEAD, a TLS AEAD may only be used in one direction. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); return 0; } if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } if (max_out_len < in_len) { // This requires that the caller provide space for the MAC, even though it // will always be removed on return. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); return 0; } if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); return 0; } if (ad_len != 13 - 2 /* length bytes */) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); return 0; } if (in_len > INT_MAX) { // EVP_CIPHER takes int as input. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); return 0; } // Configure the explicit IV. if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && !tls_ctx->implicit_iv && !EVP_DecryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) { return 0; } // Decrypt to get the plaintext + MAC + padding. size_t total = 0; int len; if (!EVP_DecryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, (int)in_len)) { return 0; } total += len; if (!EVP_DecryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) { return 0; } total += len; assert(total == in_len); // Remove CBC padding. Code from here on is timing-sensitive with respect to // |padding_ok| and |data_plus_mac_len| for CBC ciphers. size_t data_plus_mac_len; crypto_word_t padding_ok; if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) { if (!EVP_tls_cbc_remove_padding( &padding_ok, &data_plus_mac_len, out, total, EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx), HMAC_size(&tls_ctx->hmac_ctx))) { // Publicly invalid. This can be rejected in non-constant time. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } } else { padding_ok = CONSTTIME_TRUE_W; data_plus_mac_len = total; // |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has // already been checked against the MAC size at the top of the function. assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx)); } size_t data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx); // At this point, if the padding is valid, the first |data_plus_mac_len| bytes // after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is // still large enough to extract a MAC, but it will be irrelevant. // To allow for CBC mode which changes cipher length, |ad| doesn't include the // length for legacy ciphers. uint8_t ad_fixed[13]; OPENSSL_memcpy(ad_fixed, ad, 11); ad_fixed[11] = (uint8_t)(data_len >> 8); ad_fixed[12] = (uint8_t)(data_len & 0xff); ad_len += 2; // Compute the MAC and extract the one in the record. uint8_t mac[EVP_MAX_MD_SIZE]; size_t mac_len; uint8_t record_mac_tmp[EVP_MAX_MD_SIZE]; uint8_t *record_mac; if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx.md)) { if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx.md, mac, &mac_len, ad_fixed, out, data_plus_mac_len, total, tls_ctx->mac_key, tls_ctx->mac_key_len)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx)); record_mac = record_mac_tmp; EVP_tls_cbc_copy_mac(record_mac, mac_len, out, data_plus_mac_len, total); } else { // We should support the constant-time path for all CBC-mode ciphers // implemented. assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE); unsigned mac_len_u; if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || !HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) || !HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) || !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) { return 0; } mac_len = mac_len_u; assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx)); record_mac = &out[data_len]; } // Perform the MAC check and the padding check in constant-time. It should be // safe to simply perform the padding check first, but it would not be under a // different choice of MAC location on padding failure. See // EVP_tls_cbc_remove_padding. crypto_word_t good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len), 0); good &= padding_ok; if (!good) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } // End of timing-sensitive code. *out_len = data_len; return 1; }
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; BIGNUM *tmp_a; // p must be a prime > 3 if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD); return 0; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); tmp_a = BN_CTX_get(ctx); if (tmp_a == NULL) { goto err; } // group->field if (!BN_copy(&group->field, p)) { goto err; } BN_set_negative(&group->field, 0); // Store the field in minimal form, so it can be used with |BN_ULONG| arrays. bn_set_minimal_width(&group->field); // group->a if (!BN_nnmod(tmp_a, a, &group->field, ctx)) { goto err; } if (group->meth->field_encode) { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) { goto err; } } else if (!BN_copy(&group->a, tmp_a)) { goto err; } // group->b if (!BN_nnmod(&group->b, b, &group->field, ctx)) { goto err; } if (group->meth->field_encode && !group->meth->field_encode(group, &group->b, &group->b, ctx)) { goto err; } // group->a_is_minus3 if (!BN_add_word(tmp_a, 3)) { goto err; } group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); if (group->meth->field_encode != NULL) { if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) { goto err; } } else if (!BN_copy(&group->one, BN_value_one())) { goto err; } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
int dtls1_accept(SSL *s) { BUF_MEM *buf; void (*cb)(const SSL *ssl,int type,int val)=NULL; unsigned long alg_a; int ret= -1; int new_state,state,skip=0; int listen; ERR_clear_error(); ERR_clear_system_error(); if (s->info_callback != NULL) cb=s->info_callback; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; listen = s->d1->listen; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->d1->listen = listen; if (s->cert == NULL) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_NO_CERTIFICATE_SET); return(-1); } for (;;) { state=s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate=1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); return -1; } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) { if ((buf=BUF_MEM_new()) == NULL) { ret= -1; goto end; } if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) { ret= -1; goto end; } s->init_buf=buf; } if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } s->init_num=0; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) * ...but not with SCTP :-) */ if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret=ssl3_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; ssl3_init_finished_mac(s); break; case SSL3_ST_SW_HELLO_REQ_C: s->state=SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: case SSL3_ST_SR_CLNT_HELLO_D: s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; /* Reflect ClientHello sequence to remain stateless while listening */ if (listen) { memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); } /* If we're just listening, stop here */ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; s->d1->listen = 0; /* Set expected sequence numbers * to continue the handshake. */ s->d1->handshake_read_seq = 2; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; goto end; } break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: ret = dtls1_send_hello_verify_request(s); if ( ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC */ ssl3_init_finished_mac(s); break; case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); ret=ssl3_send_server_hello(s); if (ret <= 0) goto end; if (s->hit) { if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else s->state=SSL3_ST_SW_CHANGE_A; } else s->state=SSL3_ST_SW_CERT_A; s->init_num=0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or normal PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); ret=ssl3_send_server_certificate(s); if (ret <= 0) goto end; if (s->tlsext_status_expected) s->state=SSL3_ST_SW_CERT_STATUS_A; else s->state=SSL3_ST_SW_KEY_EXCH_A; } else { skip = 1; s->state=SSL3_ST_SW_KEY_EXCH_A; } s->init_num=0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* Send a ServerKeyExchange message if: * - The key exchange is ephemeral or anonymous * Diffie-Hellman. * - There is a PSK identity hint. * * TODO(davidben): This logic is currently duplicated * in s3_srvr.c. Fix this. In the meantime, keep them * in sync. */ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || ((alg_a & SSL_aPSK) && s->session->psk_identity_hint)) { dtls1_start_timer(s); ret=ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; } else skip=1; s->state=SSL3_ST_SW_CERT_REQ_A; s->init_num=0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: if (/* don't request cert unless asked for it: */ !(s->verify_mode & SSL_VERIFY_PEER) || /* if SSL_VERIFY_CLIENT_ONCE is set, * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || /* never request cert in anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246): */ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && /* ... except when the application insists on verification * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* With normal PSK Certificates and * Certificate Requests are omitted */ (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip=1; s->s3->tmp.cert_request=0; s->state=SSL3_ST_SW_SRVR_DONE_A; } else { s->s3->tmp.cert_request=1; dtls1_start_timer(s); ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; #else s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; #endif s->init_num=0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret=ssl3_send_server_done(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; break; case SSL3_ST_SW_FLUSH: s->rwstate=SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; } ret= -1; goto end; } s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: if (s->s3->tmp.cert_request) { ret=ssl3_get_client_certificate(s); if (ret <= 0) goto end; } s->init_num=0; s->state=SSL3_ST_SR_KEY_EXCH_A; break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: ret=ssl3_get_client_key_exchange(s); if (ret <= 0) goto end; s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; /* TODO(davidben): These two blocks are different * between SSL and DTLS. Resolve the difference and code * duplication. */ if (SSL_USE_SIGALGS(s)) { if (!s->session->peer) break; /* For sigalgs freeze the handshake buffer * at this point and digest cached records. */ if (!s->s3->handshake_buffer) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); return -1; } s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; if (!ssl3_digest_cached_records(s)) return -1; } else { /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; s->state=SSL3_ST_SR_FINISHED_A; s->init_num=0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; dtls1_stop_timer(s); if (s->hit) s->state=SSL_ST_OK; else if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret=ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret=ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_KEY_EXCH_A; s->init_num=0; break; case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret= -1; goto end; } ret=dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FINISHED_A; s->init_num=0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret= -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret=ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) { s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; } else { s->s3->tmp.next_state=SSL_ST_OK; } s->init_num=0; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); #if 0 BUF_MEM_free(s->init_buf); s->init_buf=NULL; #endif /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num=0; if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { s->renegotiate=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func=dtls1_accept; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; /* break; */ default: OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_UNKNOWN_STATE); ret= -1; goto end; /* break; */ } if (!s->s3->tmp.reuse_message && !skip) { if (s->debug) { if ((ret=BIO_flush(s->wbio)) <= 0) goto end; } if ((cb != NULL) && (s->state != state)) { new_state=s->state; s->state=state; cb(s,SSL_CB_ACCEPT_LOOP,1); s->state=new_state; } } skip=0; } end: /* BIO_flush(s->wbio); */ s->in_handshake--; if (cb != NULL) cb(s,SSL_CB_ACCEPT_EXIT,ret); return(ret); }
static int conn_state(BIO *bio, BIO_CONNECT *c) { int ret = -1, i; char *p, *q; int (*cb)(const BIO *, int, int) = NULL; if (c->info_callback != NULL) { cb = c->info_callback; } for (;;) { switch (c->state) { case BIO_CONN_S_BEFORE: p = c->param_hostname; if (p == NULL) { OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_HOSTNAME_SPECIFIED); goto exit_loop; } for (; *p != 0; p++) { if (*p == ':' || *p == '/') { break; } } i = *p; if (i == ':' || i == '/') { *(p++) = 0; if (i == ':') { for (q = p; *q; q++) { if (*q == '/') { *q = 0; break; } } if (c->param_port != NULL) { OPENSSL_free(c->param_port); } c->param_port = BUF_strdup(p); } } if (c->param_port == NULL) { OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_PORT_SPECIFIED); ERR_add_error_data(2, "host=", c->param_hostname); goto exit_loop; } if (!bio_ip_and_port_to_socket_and_addr( &bio->num, &c->them, &c->them_length, c->param_hostname, c->param_port)) { OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_UNABLE_TO_CREATE_SOCKET); ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); goto exit_loop; } memset(c->ip, 0, 4); maybe_copy_ipv4_address(c->ip, &c->them); if (c->nbio) { if (!bio_socket_nbio(bio->num, 1)) { OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_ERROR_SETTING_NBIO); ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); goto exit_loop; } } i = 1; ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof(i)); if (ret < 0) { OPENSSL_PUT_SYSTEM_ERROR(setsockopt); OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_KEEPALIVE); ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); goto exit_loop; } BIO_clear_retry_flags(bio); ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length); if (ret < 0) { if (bio_fd_should_retry(ret)) { BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY)); c->state = BIO_CONN_S_BLOCKED_CONNECT; bio->retry_reason = BIO_RR_CONNECT; } else { OPENSSL_PUT_SYSTEM_ERROR(connect); OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_CONNECT_ERROR); ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); } goto exit_loop; } else { c->state = BIO_CONN_S_OK; } break; case BIO_CONN_S_BLOCKED_CONNECT: i = bio_sock_error(bio->num); if (i) { if (bio_fd_should_retry(ret)) { BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY)); c->state = BIO_CONN_S_BLOCKED_CONNECT; bio->retry_reason = BIO_RR_CONNECT; ret = -1; } else { BIO_clear_retry_flags(bio); OPENSSL_PUT_SYSTEM_ERROR(connect); OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NBIO_CONNECT_ERROR); ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); ret = 0; } goto exit_loop; } else { c->state = BIO_CONN_S_OK; } break; case BIO_CONN_S_OK: ret = 1; goto exit_loop; default: assert(0); goto exit_loop; } if (cb != NULL) { ret = cb((BIO *)bio, c->state, ret); if (ret == 0) { goto end; } } } exit_loop: if (cb != NULL) { ret = cb((BIO *)bio, c->state, ret); } end: return ret; }
BN_BLINDING *BN_BLINDING_create_param( BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont) { int retry_counter = 32; BN_BLINDING *ret = NULL; if (b == NULL) { ret = BN_BLINDING_new(NULL, NULL, m); } else { ret = b; } if (ret == NULL) { goto err; } if (ret->A == NULL && (ret->A = BN_new()) == NULL) { goto err; } if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) { goto err; } if (e != NULL) { BN_free(ret->e); ret->e = BN_dup(e); } if (ret->e == NULL) { goto err; } if (mont != NULL) { ret->mont = mont; } do { if (!BN_rand_range(ret->A, ret->mod)) { goto err; } int no_inverse; if (BN_mod_inverse_ex(ret->Ai, &no_inverse, ret->A, ret->mod, ctx) == NULL) { /* this should almost never happen for good RSA keys */ if (no_inverse) { if (retry_counter-- == 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS); goto err; } ERR_clear_error(); } else { goto err; } } else { break; } } while (1); if (!BN_mod_exp_mont(ret->A, ret->A, ret->e, ret->mod, ctx, ret->mont)) { goto err; } return ret; err: if (b == NULL) { BN_BLINDING_free(ret); ret = NULL; } return ret; }
int dtls1_accept(SSL *s) { BUF_MEM *buf = NULL; void (*cb)(const SSL *ssl, int type, int val) = NULL; uint32_t alg_a; int ret = -1; int new_state, state, skip = 0; assert(s->handshake_func == dtls1_accept); assert(s->server); assert(SSL_IS_DTLS(s)); ERR_clear_error(); ERR_clear_system_error(); if (s->info_callback != NULL) { cb = s->info_callback; } else if (s->ctx->info_callback != NULL) { cb = s->ctx->info_callback; } s->in_handshake++; if (s->cert == NULL) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_NO_CERTIFICATE_SET); return -1; } for (;;) { state = s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate = 1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_ACCEPT: case SSL_ST_BEFORE | SSL_ST_ACCEPT: if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_START, 1); } if (s->init_buf == NULL) { buf = BUF_MEM_new(); if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; goto end; } s->init_buf = buf; buf = NULL; } if (!ssl3_setup_buffers(s)) { ret = -1; goto end; } s->init_num = 0; if (s->state != SSL_ST_RENEGOTIATE) { if (!ssl_init_wbio_buffer(s, 1)) { ret = -1; goto end; } if (!ssl3_init_finished_mac(s)) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); ret = -1; goto end; } s->state = SSL3_ST_SR_CLNT_HELLO_A; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a * HelloRequest */ s->state = SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown = 0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret = ssl3_send_hello_request(s); if (ret <= 0) { goto end; } s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A; s->state = SSL3_ST_SW_FLUSH; s->init_num = 0; if (!ssl3_init_finished_mac(s)) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); ret = -1; goto end; } break; case SSL3_ST_SW_HELLO_REQ_C: s->state = SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: case SSL3_ST_SR_CLNT_HELLO_D: s->shutdown = 0; ret = ssl3_get_client_hello(s); if (ret <= 0) { goto end; } dtls1_stop_timer(s); s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num = 0; break; case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); ret = ssl3_send_server_hello(s); if (ret <= 0) { goto end; } if (s->hit) { if (s->tlsext_ticket_expected) { s->state = SSL3_ST_SW_SESSION_TICKET_A; } else { s->state = SSL3_ST_SW_CHANGE_A; } } else { s->state = SSL3_ST_SW_CERT_A; } s->init_num = 0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { dtls1_start_timer(s); ret = ssl3_send_server_certificate(s); if (ret <= 0) { goto end; } if (s->s3->tmp.certificate_status_expected) { s->state = SSL3_ST_SW_CERT_STATUS_A; } else { s->state = SSL3_ST_SW_KEY_EXCH_A; } } else { skip = 1; s->state = SSL3_ST_SW_KEY_EXCH_A; } s->init_num = 0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* Send a ServerKeyExchange message if: * - The key exchange is ephemeral or anonymous * Diffie-Hellman. * - There is a PSK identity hint. * * TODO(davidben): This logic is currently duplicated * in s3_srvr.c. Fix this. In the meantime, keep them * in sync. */ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || ((alg_a & SSL_aPSK) && s->psk_identity_hint)) { dtls1_start_timer(s); ret = ssl3_send_server_key_exchange(s); if (ret <= 0) { goto end; } } else { skip = 1; } s->state = SSL3_ST_SW_CERT_REQ_A; s->init_num = 0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: if (/* don't request cert unless asked for it: */ !(s->verify_mode & SSL_VERIFY_PEER) || /* if SSL_VERIFY_CLIENT_ONCE is set, * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || /* With normal PSK Certificates and * Certificate Requests are omitted */ (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip = 1; s->s3->tmp.cert_request = 0; s->state = SSL3_ST_SW_SRVR_DONE_A; } else { s->s3->tmp.cert_request = 1; dtls1_start_timer(s); ret = ssl3_send_certificate_request(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_SRVR_DONE_A; s->init_num = 0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret = ssl3_send_server_done(s); if (ret <= 0) { goto end; } s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; s->state = SSL3_ST_SW_FLUSH; s->init_num = 0; break; case SSL3_ST_SW_FLUSH: s->rwstate = SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { ret = -1; goto end; } s->rwstate = SSL_NOTHING; s->state = s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: if (s->s3->tmp.cert_request) { ret = ssl3_get_client_certificate(s); if (ret <= 0) { goto end; } } s->init_num = 0; s->state = SSL3_ST_SR_KEY_EXCH_A; break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: ret = ssl3_get_client_key_exchange(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: ret = ssl3_get_cert_verify(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SR_FINISHED_A; s->init_num = 0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret = ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) { goto end; } dtls1_stop_timer(s); if (s->hit) { s->state = SSL_ST_OK; } else if (s->tlsext_ticket_expected) { s->state = SSL3_ST_SW_SESSION_TICKET_A; } else { s->state = SSL3_ST_SW_CHANGE_A; } s->init_num = 0; break; case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret = ssl3_send_new_session_ticket(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_CHANGE_A; s->init_num = 0; break; case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher = s->s3->tmp.new_cipher; if (!s->enc_method->setup_key_block(s)) { ret = -1; goto end; } ret = dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A, SSL3_ST_SW_CHANGE_B); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_FINISHED_A; s->init_num = 0; if (!s->enc_method->change_cipher_state( s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret = -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret = ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B, s->enc_method->server_finished_label, s->enc_method->server_finished_label_len); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_FLUSH; if (s->hit) { s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A; } else { s->s3->tmp.next_state = SSL_ST_OK; } s->init_num = 0; break; case SSL_ST_OK: ssl3_cleanup_key_block(s); /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num = 0; if (s->renegotiate == 2) { /* skipped if we just sent a HelloRequest */ s->renegotiate = 0; s->new_session = 0; ssl_update_cache(s, SSL_SESS_CACHE_SERVER); if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_DONE, 1); } } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; default: OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_UNKNOWN_STATE); ret = -1; goto end; } if (!s->s3->tmp.reuse_message && !skip) { if (cb != NULL && s->state != state) { new_state = s->state; s->state = state; cb(s, SSL_CB_ACCEPT_LOOP, 1); s->state = new_state; } } skip = 0; } end: s->in_handshake--; BUF_MEM_free(buf); if (cb != NULL) { cb(s, SSL_CB_ACCEPT_EXIT, ret); } return ret; }
/* Read a file that contains our certificate in "PEM" format, possibly followed * by a sequence of CA certificates that should be sent to the peer in the * Certificate message. */ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) { BIO *in; int ret = 0; X509 *x = NULL; ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ in = BIO_new(BIO_s_file()); if (in == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); goto end; } if (BIO_read_filename(in, file) <= 0) { OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); goto end; } x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata); if (x == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB); goto end; } ret = SSL_CTX_use_certificate(ctx, x); if (ERR_peek_error() != 0) { ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ } if (ret) { /* If we could set up our certificate, now proceed to the CA * certificates. */ X509 *ca; int r; uint32_t err; SSL_CTX_clear_chain_certs(ctx); while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata)) != NULL) { r = SSL_CTX_add0_chain_cert(ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /* Note that we must not free r if it was successfully added to the chain * (while we must free the main certificate, since its reference count is * increased by SSL_CTX_use_certificate). */ } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { ret = 0; /* some real error */ } } end: X509_free(x); BIO_free(in); return ret; }
static int ssl3_handshake_mac(SSL *s, int md_nid, const char *sender, int len, uint8_t *p) { unsigned int ret; int npad, n; unsigned int i; uint8_t md_buf[EVP_MAX_MD_SIZE]; EVP_MD_CTX ctx, *d = NULL; if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer)) { return 0; } /* Search for digest of specified type in the handshake_dgst array. */ for (i = 0; i < SSL_MAX_DIGEST; i++) { if (s->s3->handshake_dgst[i] && EVP_MD_CTX_type(s->s3->handshake_dgst[i]) == md_nid) { d = s->s3->handshake_dgst[i]; break; } } if (!d) { OPENSSL_PUT_ERROR(SSL, ssl3_handshake_mac, SSL_R_NO_REQUIRED_DIGEST); return 0; } EVP_MD_CTX_init(&ctx); if (!EVP_MD_CTX_copy_ex(&ctx, d)) { EVP_MD_CTX_cleanup(&ctx); OPENSSL_PUT_ERROR(SSL, ssl3_handshake_mac, ERR_LIB_EVP); return 0; } n = EVP_MD_CTX_size(&ctx); if (n < 0) { return 0; } npad = (48 / n) * n; if (sender != NULL) { EVP_DigestUpdate(&ctx, sender, len); } EVP_DigestUpdate(&ctx, s->session->master_key, s->session->master_key_length); EVP_DigestUpdate(&ctx, ssl3_pad_1, npad); EVP_DigestFinal_ex(&ctx, md_buf, &i); if (!EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL)) { EVP_MD_CTX_cleanup(&ctx); OPENSSL_PUT_ERROR(SSL, ssl3_handshake_mac, ERR_LIB_EVP); return 0; } EVP_DigestUpdate(&ctx, s->session->master_key, s->session->master_key_length); EVP_DigestUpdate(&ctx, ssl3_pad_2, npad); EVP_DigestUpdate(&ctx, md_buf, i); EVP_DigestFinal_ex(&ctx, p, &ret); EVP_MD_CTX_cleanup(&ctx); return ret; }
int ssl3_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret, size_t secret_len, const char *label, size_t label_len, const uint8_t *seed1, size_t seed1_len, const uint8_t *seed2, size_t seed2_len) { EVP_MD_CTX md5; EVP_MD_CTX sha1; uint8_t buf[16], smd[SHA_DIGEST_LENGTH]; uint8_t c = 'A'; size_t i, j, k; k = 0; EVP_MD_CTX_init(&md5); EVP_MD_CTX_init(&sha1); for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) { k++; if (k > sizeof(buf)) { /* bug: 'buf' is too small for this ciphersuite */ OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_R_INTERNAL_ERROR); return 0; } for (j = 0; j < k; j++) { buf[j] = c; } c++; if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) { OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_LIB_EVP); return 0; } EVP_DigestUpdate(&sha1, buf, k); EVP_DigestUpdate(&sha1, secret, secret_len); /* |label| is ignored for SSLv3. */ if (seed1_len) { EVP_DigestUpdate(&sha1, seed1, seed1_len); } if (seed2_len) { EVP_DigestUpdate(&sha1, seed2, seed2_len); } EVP_DigestFinal_ex(&sha1, smd, NULL); if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) { OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_LIB_EVP); return 0; } EVP_DigestUpdate(&md5, secret, secret_len); EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH); if (i + MD5_DIGEST_LENGTH > out_len) { EVP_DigestFinal_ex(&md5, smd, NULL); memcpy(out, smd, out_len - i); } else { EVP_DigestFinal_ex(&md5, out, NULL); } out += MD5_DIGEST_LENGTH; } OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH); EVP_MD_CTX_cleanup(&md5); EVP_MD_CTX_cleanup(&sha1); return 1; }
static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len, const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad, size_t ad_len) { AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; size_t total = 0; if (!ssl3_ctx->cipher_ctx.encrypt) { /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); return 0; } if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len || in_len > INT_MAX) { /* EVP_CIPHER takes int as input. */ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); return 0; } if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); return 0; } if (nonce_len != 0) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE); return 0; } if (ad_len != 11 - 2 /* length bytes */) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); return 0; } /* Compute the MAC. This must be first in case the operation is being done * in-place. */ uint8_t mac[EVP_MAX_MD_SIZE]; unsigned mac_len; if (!ssl3_mac(ssl3_ctx, mac, &mac_len, ad, ad_len, in, in_len)) { return 0; } /* Encrypt the input. */ int len; if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, (int)in_len)) { return 0; } total = len; /* Feed the MAC into the cipher. */ if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, mac, (int)mac_len)) { return 0; } total += len; unsigned block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx); if (block_size > 1) { assert(block_size <= 256); assert(EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE); /* Compute padding and feed that into the cipher. */ uint8_t padding[256]; unsigned padding_len = block_size - ((in_len + mac_len) % block_size); memset(padding, 0, padding_len - 1); padding[padding_len - 1] = padding_len - 1; if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, padding, (int)padding_len)) { return 0; } total += len; } if (!EVP_EncryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) { return 0; } total += len; *out_len = total; return 1; }
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) { int *ip; const char **pptr; long ret = 1; BIO_CONNECT *data; data = (BIO_CONNECT *)bio->ptr; switch (cmd) { case BIO_CTRL_RESET: ret = 0; data->state = BIO_CONN_S_BEFORE; conn_close_socket(bio); bio->flags = 0; break; case BIO_C_DO_STATE_MACHINE: /* use this one to start the connection */ if (data->state != BIO_CONN_S_OK) ret = (long)conn_state(bio, data); else ret = 1; break; case BIO_C_GET_CONNECT: /* TODO(fork): can this be removed? (Or maybe this whole file). */ if (ptr != NULL) { pptr = (const char **)ptr; if (num == 0) { *pptr = data->param_hostname; } else if (num == 1) { *pptr = data->param_port; } else if (num == 2) { *pptr = (char *) &data->ip[0]; } else if (num == 3) { *((int *)ptr) = data->port; } if (!bio->init) { *pptr = "not initialized"; } ret = 1; } break; case BIO_C_SET_CONNECT: if (ptr != NULL) { bio->init = 1; if (num == 0) { if (data->param_hostname != NULL) { OPENSSL_free(data->param_hostname); } data->param_hostname = BUF_strdup(ptr); } else if (num == 1) { if (data->param_port != NULL) { OPENSSL_free(data->param_port); } data->param_port = BUF_strdup(ptr); } else { ret = 0; } } break; case BIO_C_SET_NBIO: data->nbio = (int)num; break; case BIO_C_GET_FD: if (bio->init) { ip = (int *)ptr; if (ip != NULL) { *ip = bio->num; } ret = 1; } else { ret = 0; } break; case BIO_CTRL_GET_CLOSE: ret = bio->shutdown; break; case BIO_CTRL_SET_CLOSE: bio->shutdown = (int)num; break; case BIO_CTRL_PENDING: case BIO_CTRL_WPENDING: ret = 0; break; case BIO_CTRL_FLUSH: break; case BIO_CTRL_SET_CALLBACK: { #if 0 /* FIXME: Should this be used? -- Richard Levitte */ OPENSSL_PUT_ERROR(BIO, XXX, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ret = -1; #else ret = 0; #endif } break; case BIO_CTRL_GET_CALLBACK: { int (**fptr)(const BIO *bio, int state, int xret); fptr = (int (**)(const BIO *bio, int state, int xret))ptr; *fptr = data->info_callback; } break; default: ret = 0; break; } return (ret); }
static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len, const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad, size_t ad_len) { AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; if (ssl3_ctx->cipher_ctx.encrypt) { /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); return 0; } size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx); if (in_len < mac_len) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } if (max_out_len < in_len) { /* This requires that the caller provide space for the MAC, even though it * will always be removed on return. */ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); return 0; } if (nonce_len != 0) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); return 0; } if (ad_len != 11 - 2 /* length bytes */) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); return 0; } if (in_len > INT_MAX) { /* EVP_CIPHER takes int as input. */ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); return 0; } /* Decrypt to get the plaintext + MAC + padding. */ size_t total = 0; int len; if (!EVP_DecryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, (int)in_len)) { return 0; } total += len; if (!EVP_DecryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) { return 0; } total += len; assert(total == in_len); /* Remove CBC padding and MAC. This would normally be timing-sensitive, but SSLv3 CBC * ciphers are already broken. Support will be removed eventually. * https://www.openssl.org/~bodo/ssl-poodle.pdf */ unsigned data_len; if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) { unsigned padding_length = out[total - 1]; if (total < padding_length + 1 + mac_len) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } /* The padding must be minimal. */ if (padding_length + 1 > EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } data_len = total - padding_length - 1 - mac_len; } else { data_len = total - mac_len; } /* Compute the MAC and compare against the one in the record. */ uint8_t mac[EVP_MAX_MD_SIZE]; if (!ssl3_mac(ssl3_ctx, mac, NULL, ad, ad_len, out, data_len)) { return 0; } if (CRYPTO_memcmp(&out[data_len], mac, mac_len) != 0) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } *out_len = data_len; return 1; }
/* TODO(davidben): Is there any reason this doesn't call * |SSL_add_file_cert_subjects_to_stack|? */ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) { BIO *in; X509 *x = NULL; X509_NAME *xn = NULL; STACK_OF(X509_NAME) *ret = NULL, *sk; sk = sk_X509_NAME_new(xname_cmp); in = BIO_new(BIO_s_file()); if (sk == NULL || in == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!BIO_read_filename(in, file)) { goto err; } for (;;) { if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { break; } if (ret == NULL) { ret = sk_X509_NAME_new_null(); if (ret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } xn = X509_get_subject_name(x); if (xn == NULL) { goto err; } /* check for duplicates */ xn = X509_NAME_dup(xn); if (xn == NULL) { goto err; } if (sk_X509_NAME_find(sk, NULL, xn)) { X509_NAME_free(xn); } else { sk_X509_NAME_push(sk, xn); sk_X509_NAME_push(ret, xn); } } if (0) { err: sk_X509_NAME_pop_free(ret, X509_NAME_free); ret = NULL; } sk_X509_NAME_free(sk); BIO_free(in); X509_free(x); if (ret != NULL) { ERR_clear_error(); } return ret; }
int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type, enum evp_aead_direction_t direction, const uint8_t *traffic_secret, size_t traffic_secret_len) { if (traffic_secret_len > 0xff) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return 0; } const char *phase; switch (type) { case type_early_handshake: phase = "early handshake key expansion, "; break; case type_early_data: phase = "early application data key expansion, "; break; case type_handshake: phase = "handshake key expansion, "; break; case type_data: phase = "application data key expansion, "; break; default: return 0; } size_t phase_len = strlen(phase); const char *purpose = "client write key"; if ((ssl->server && direction == evp_aead_seal) || (!ssl->server && direction == evp_aead_open)) { purpose = "server write key"; } size_t purpose_len = strlen(purpose); /* The longest label has length 38 (type_early_data) + 16 (either purpose * value). */ uint8_t label[38 + 16]; size_t label_len = phase_len + purpose_len; if (label_len > sizeof(label)) { assert(0); return 0; } memcpy(label, phase, phase_len); memcpy(label + phase_len, purpose, purpose_len); /* Look up cipher suite properties. */ const EVP_AEAD *aead; const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); size_t mac_secret_len, fixed_iv_len; if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len, ssl->session->cipher, ssl3_protocol_version(ssl))) { return 0; } /* Derive the key. */ size_t key_len = EVP_AEAD_key_length(aead); uint8_t key[EVP_AEAD_MAX_KEY_LENGTH]; if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, label, label_len, NULL, 0, key_len)) { return 0; } /* The IV's label ends in "iv" instead of "key". */ if (label_len < 3) { assert(0); return 0; } label_len--; label[label_len - 2] = 'i'; label[label_len - 1] = 'v'; /* Derive the IV. */ size_t iv_len = EVP_AEAD_nonce_length(aead); uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH]; if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, label, label_len, NULL, 0, iv_len)) { return 0; } SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(direction, ssl3_protocol_version(ssl), ssl->session->cipher, key, key_len, NULL, 0, iv, iv_len); if (traffic_aead == NULL) { return 0; } if (direction == evp_aead_open) { if (!ssl->method->set_read_state(ssl, traffic_aead)) { return 0; } } else { if (!ssl->method->set_write_state(ssl, traffic_aead)) { return 0; } } /* Save the traffic secret. */ if (direction == evp_aead_open) { memcpy(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len); ssl->s3->read_traffic_secret_len = traffic_secret_len; } else { memcpy(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len); ssl->s3->write_traffic_secret_len = traffic_secret_len; } return 1; }
int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len, const uint8_t *from, unsigned from_len) { if (from_len == 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY); return -1; } /* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography * Standard", section 7.2.2. */ if (from_len < RSA_PKCS1_PADDING_SIZE) { /* |from| is zero-padded to the size of the RSA modulus, a public value, so * this can be rejected in non-constant time. */ OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); return -1; } unsigned first_byte_is_zero = constant_time_eq(from[0], 0); unsigned second_byte_is_two = constant_time_eq(from[1], 2); unsigned i, zero_index = 0, looking_for_index = ~0u; for (i = 2; i < from_len; i++) { unsigned equals0 = constant_time_is_zero(from[i]); zero_index = constant_time_select(looking_for_index & equals0, (unsigned)i, zero_index); looking_for_index = constant_time_select(equals0, 0, looking_for_index); } /* The input must begin with 00 02. */ unsigned valid_index = first_byte_is_zero; valid_index &= second_byte_is_two; /* We must have found the end of PS. */ valid_index &= ~looking_for_index; /* PS must be at least 8 bytes long, and it starts two bytes into |from|. */ valid_index &= constant_time_ge(zero_index, 2 + 8); /* Skip the zero byte. */ zero_index++; /* NOTE: Although this logic attempts to be constant time, the API contracts * of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it * impossible to completely avoid Bleichenbacher's attack. Consumers should * use |RSA_unpad_key_pkcs1|. */ if (!valid_index) { OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR); return -1; } const unsigned msg_len = from_len - zero_index; if (msg_len > to_len) { /* This shouldn't happen because this function is always called with * |to_len| as the key size and |from_len| is bounded by the key size. */ OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR); return -1; } if (msg_len > INT_MAX) { OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); return -1; } memcpy(to, &from[zero_index], msg_len); return (int)msg_len; }
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *tmp, *tmp_Z; BIGNUM **prod_Z = NULL; int ret = 0; if (num == 0) { return 1; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); tmp_Z = BN_CTX_get(ctx); if (tmp == NULL || tmp_Z == NULL) { goto err; } prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0])); if (prod_Z == NULL) { goto err; } OPENSSL_memset(prod_Z, 0, num * sizeof(prod_Z[0])); for (size_t i = 0; i < num; i++) { prod_Z[i] = BN_new(); if (prod_Z[i] == NULL) { goto err; } } // Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, // skipping any zero-valued inputs (pretend that they're 1). if (!BN_is_zero(&points[0]->Z)) { if (!BN_copy(prod_Z[0], &points[0]->Z)) { goto err; } } else { if (BN_copy(prod_Z[0], &group->one) == NULL) { goto err; } } for (size_t i = 1; i < num; i++) { if (!BN_is_zero(&points[i]->Z)) { if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], &points[i]->Z, ctx)) { goto err; } } else { if (!BN_copy(prod_Z[i], prod_Z[i - 1])) { goto err; } } } // Now use a single explicit inversion to replace every non-zero points[i]->Z // by its inverse. We use |BN_mod_inverse_odd| instead of doing a constant- // time inversion using Fermat's Little Theorem because this function is // usually only used for converting multiples of a public key point to // affine, and a public key point isn't secret. If we were to use Fermat's // Little Theorem then the cost of the inversion would usually be so high // that converting the multiples to affine would be counterproductive. int no_inverse; if (!BN_mod_inverse_odd(tmp, &no_inverse, prod_Z[num - 1], &group->field, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (group->meth->field_encode != NULL) { // In the Montgomery case, we just turned R*H (representing H) // into 1/(R*H), but we need R*(1/H) (representing 1/H); // i.e. we need to multiply by the Montgomery factor twice. if (!group->meth->field_encode(group, tmp, tmp, ctx) || !group->meth->field_encode(group, tmp, tmp, ctx)) { goto err; } } for (size_t i = num - 1; i > 0; --i) { // Loop invariant: tmp is the product of the inverses of // points[0]->Z .. points[i]->Z (zero-valued inputs skipped). if (BN_is_zero(&points[i]->Z)) { continue; } // Set tmp_Z to the inverse of points[i]->Z (as product // of Z inverses 0 .. i, Z values 0 .. i - 1). if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx) || // Update tmp to satisfy the loop invariant for i - 1. !group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx) || // Replace points[i]->Z by its inverse. !BN_copy(&points[i]->Z, tmp_Z)) { goto err; } } // Replace points[0]->Z by its inverse. if (!BN_is_zero(&points[0]->Z) && !BN_copy(&points[0]->Z, tmp)) { goto err; } // Finally, fix up the X and Y coordinates for all points. for (size_t i = 0; i < num; i++) { EC_POINT *p = points[i]; if (!BN_is_zero(&p->Z)) { // turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1). if (!group->meth->field_sqr(group, tmp, &p->Z, ctx) || !group->meth->field_mul(group, &p->X, &p->X, tmp, ctx) || !group->meth->field_mul(group, tmp, tmp, &p->Z, ctx) || !group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) { goto err; } if (BN_copy(&p->Z, &group->one) == NULL) { goto err; } } } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); if (prod_Z != NULL) { for (size_t i = 0; i < num; i++) { if (prod_Z[i] == NULL) { break; } BN_clear_free(prod_Z[i]); } OPENSSL_free(prod_Z); } return ret; }
static int bn_rand_with_additional_data(BIGNUM *rnd, int bits, int top, int bottom, const uint8_t additional_data[32]) { uint8_t *buf = NULL; int ret = 0, bit, bytes, mask; if (rnd == NULL) { return 0; } if (top != BN_RAND_TOP_ANY && top != BN_RAND_TOP_ONE && top != BN_RAND_TOP_TWO) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (bottom != BN_RAND_BOTTOM_ANY && bottom != BN_RAND_BOTTOM_ODD) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (bits == 0) { BN_zero(rnd); return 1; } bytes = (bits + 7) / 8; bit = (bits - 1) % 8; mask = 0xff << (bit + 1); buf = OPENSSL_malloc(bytes); if (buf == NULL) { OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); goto err; } /* Make a random number and set the top and bottom bits. */ RAND_bytes_with_additional_data(buf, bytes, additional_data); if (top != BN_RAND_TOP_ANY) { if (top == BN_RAND_TOP_TWO && bits > 1) { if (bit == 0) { buf[0] = 1; buf[1] |= 0x80; } else { buf[0] |= (3 << (bit - 1)); } } else { buf[0] |= (1 << bit); } } buf[0] &= ~mask; /* Set the bottom bit if requested, */ if (bottom == BN_RAND_BOTTOM_ODD) { buf[bytes - 1] |= 1; } if (!BN_bin2bn(buf, bytes, rnd)) { goto err; } ret = 1; err: if (buf != NULL) { OPENSSL_cleanse(buf, bytes); OPENSSL_free(buf); } return (ret); }
int ssl3_get_finished(SSL *s, int a, int b) { int al, finished_len, ok; long message_len; uint8_t *p; message_len = s->method->ssl_get_message(s, a, b, SSL3_MT_FINISHED, EVP_MAX_MD_SIZE, ssl_dont_hash_message, &ok); if (!ok) { return message_len; } /* Snapshot the finished hash before incorporating the new message. */ ssl3_take_mac(s); if (!ssl3_hash_current_message(s)) { goto err; } /* If this occurs, we have missed a message. * TODO(davidben): Is this check now redundant with SSL3_FLAGS_EXPECT_CCS? */ if (!s->s3->change_cipher_spec) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_A_FIN_BEFORE_A_CCS); goto f_err; } s->s3->change_cipher_spec = 0; p = s->init_msg; finished_len = s->s3->tmp.peer_finish_md_len; if (finished_len != message_len) { al = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, finished_len) != 0) { al = SSL_AD_DECRYPT_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED); goto f_err; } /* Copy the finished so we can use it for renegotiation checks */ if (s->server) { assert(finished_len <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, finished_len); s->s3->previous_client_finished_len = finished_len; } else { assert(finished_len <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, finished_len); s->s3->previous_server_finished_len = finished_len; } return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: return 0; }
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) { int ret = 0; int i, j, k, m, n, again, bufsize; unsigned char *s = NULL, *sp; unsigned char *bufp; int num = 0, slen = 0, first = 1; bs->type = V_ASN1_INTEGER; bufsize = BIO_gets(bp, buf, size); for (;;) { if (bufsize < 1) goto err_sl; i = bufsize; if (buf[i - 1] == '\n') buf[--i] = '\0'; if (i == 0) goto err_sl; if (buf[i - 1] == '\r') buf[--i] = '\0'; if (i == 0) goto err_sl; again = (buf[i - 1] == '\\'); for (j = 0; j < i; j++) { if (!(((buf[j] >= '0') && (buf[j] <= '9')) || ((buf[j] >= 'a') && (buf[j] <= 'f')) || ((buf[j] >= 'A') && (buf[j] <= 'F')))) { i = j; break; } } buf[i] = '\0'; /* * We have now cleared all the crap off the end of the line */ if (i < 2) goto err_sl; bufp = (unsigned char *)buf; if (first) { first = 0; if ((bufp[0] == '0') && (buf[1] == '0')) { bufp += 2; i -= 2; } } k = 0; i -= again; if (i % 2 != 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS); goto err; } i /= 2; if (num + i > slen) { if (s == NULL) sp = (unsigned char *)OPENSSL_malloc((unsigned int)num + i * 2); else sp = OPENSSL_realloc_clean(s, slen, num + i * 2); if (sp == NULL) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); goto err; } s = sp; slen = num + i * 2; } for (j = 0; j < i; j++, k += 2) { for (n = 0; n < 2; n++) { m = bufp[k + n]; if ((m >= '0') && (m <= '9')) m -= '0'; else if ((m >= 'a') && (m <= 'f')) m = m - 'a' + 10; else if ((m >= 'A') && (m <= 'F')) m = m - 'A' + 10; else { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS); goto err; } s[num + j] <<= 4; s[num + j] |= m; } } num += i; if (again) bufsize = BIO_gets(bp, buf, size); else break; } bs->length = num; bs->data = s; ret = 1; err: if (0) { err_sl: OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE); } if (s != NULL) OPENSSL_free(s); return (ret); }
static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) { EC_GROUP *group = NULL; EC_POINT *P = NULL; BN_CTX *ctx = NULL; BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; int ok = 0; unsigned param_len; const EC_METHOD *meth; const struct curve_data *data; const uint8_t *params; if ((ctx = BN_CTX_new()) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); goto err; } data = curve->data; param_len = data->param_len; params = data->data; if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) || !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) || !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (curve->method != 0) { meth = curve->method(); if (((group = ec_group_new(meth)) == NULL) || (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } } else { if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } } if ((P = EC_POINT_new(group)) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) || !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order) || !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } group->generator = P; P = NULL; ok = 1; err: if (!ok) { EC_GROUP_free(group); group = NULL; } EC_POINT_free(P); BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); BN_free(x); BN_free(y); return group; }
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) { const ASN1_TEMPLATE *tt = NULL; const ASN1_COMPAT_FUNCS *cf; const ASN1_EXTERN_FUNCS *ef; const ASN1_AUX *aux = it->funcs; ASN1_aux_cb *asn1_cb; ASN1_VALUE **pseqval; int i; if (aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; else asn1_cb = 0; #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_push_info(it->sname); #endif switch(it->itype) { case ASN1_ITYPE_EXTERN: ef = it->funcs; if (ef && ef->asn1_ex_new) { if (!ef->asn1_ex_new(pval, it)) goto memerr; } break; case ASN1_ITYPE_COMPAT: cf = it->funcs; if (cf && cf->asn1_new) { *pval = cf->asn1_new(); if (!*pval) goto memerr; } break; case ASN1_ITYPE_PRIMITIVE: if (it->templates) { if (!ASN1_template_new(pval, it->templates)) goto memerr; } else if (!ASN1_primitive_new(pval, it)) goto memerr; break; case ASN1_ITYPE_MSTRING: if (!ASN1_primitive_new(pval, it)) goto memerr; break; case ASN1_ITYPE_CHOICE: if (asn1_cb) { i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); if (!i) goto auxerr; if (i==2) { #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 1; } } if (!combine) { *pval = OPENSSL_malloc(it->size); if (!*pval) goto memerr; memset(*pval, 0, it->size); } asn1_set_choice_selector(pval, -1, it); if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) goto auxerr; break; case ASN1_ITYPE_NDEF_SEQUENCE: case ASN1_ITYPE_SEQUENCE: if (asn1_cb) { i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); if (!i) goto auxerr; if (i==2) { #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 1; } } if (!combine) { *pval = OPENSSL_malloc(it->size); if (!*pval) goto memerr; memset(*pval, 0, it->size); asn1_refcount_set_one(pval, it); asn1_enc_init(pval, it); } for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { pseqval = asn1_get_field_ptr(pval, tt); if (!ASN1_template_new(pseqval, tt)) goto memerr; } if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) goto auxerr; break; } #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 1; memerr: OPENSSL_PUT_ERROR(ASN1, asn1_item_ex_combine_new, ERR_R_MALLOC_FAILURE); ASN1_item_ex_free(pval, it); #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 0; auxerr: OPENSSL_PUT_ERROR(ASN1, asn1_item_ex_combine_new, ASN1_R_AUX_ERROR); ASN1_item_ex_free(pval, it); #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 0; }
/* Handle ANY DEFINED BY template, find the selector, look up the relevant * ASN1_TEMPLATE in the table and return it. */ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr) { const ASN1_ADB *adb; const ASN1_ADB_TABLE *atbl; long selector; ASN1_VALUE **sfld; int i; if (!(tt->flags & ASN1_TFLG_ADB_MASK)) { return tt; } /* Else ANY DEFINED BY ... get the table */ adb = ASN1_ADB_ptr(tt->item); /* Get the selector field */ sfld = offset2ptr(*pval, adb->offset); /* Check if NULL */ if (!sfld) { if (!adb->null_tt) { goto err; } return adb->null_tt; } /* Convert type to a long: * NB: don't check for NID_undef here because it * might be a legitimate value in the table */ if (tt->flags & ASN1_TFLG_ADB_OID) { selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); } else { selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld); } /* Try to find matching entry in table Maybe should check application types * first to allow application override? Might also be useful to have a flag * which indicates table is sorted and we can do a binary search. For now * stick to a linear search. */ for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) { if (atbl->value == selector) { return &atbl->tt; } } /* FIXME: need to search application table too */ /* No match, return default type */ if (!adb->default_tt) { goto err; } return adb->default_tt; err: /* FIXME: should log the value or OID of unsupported type */ if (nullerr) { OPENSSL_PUT_ERROR(ASN1, asn1_do_adb, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); } return NULL; }
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { int max, min, dif; register BN_ULONG t1, t2, *ap, *bp, *rp; int i, carry; max = bn_minimal_width(a); min = bn_minimal_width(b); dif = max - min; if (dif < 0) // hmm... should not be happening { OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3); return 0; } if (!bn_wexpand(r, max)) { return 0; } ap = a->d; bp = b->d; rp = r->d; carry = 0; for (i = min; i != 0; i--) { t1 = *(ap++); t2 = *(bp++); if (carry) { carry = (t1 <= t2); t1 -= t2 + 1; } else { carry = (t1 < t2); t1 -= t2; } *(rp++) = t1; } if (carry) // subtracted { if (!dif) { // error: a < b return 0; } while (dif) { dif--; t1 = *(ap++); t2 = t1 - 1; *(rp++) = t2; if (t1) { break; } } } if (dif > 0 && rp != ap) { OPENSSL_memcpy(rp, ap, sizeof(*rp) * dif); } r->width = max; r->neg = 0; bn_set_minimal_width(r); return 1; }
static int aead_tls_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag, size_t *out_tag_len, const size_t max_out_tag_len, const uint8_t *nonce, const size_t nonce_len, const uint8_t *in, const size_t in_len, const uint8_t *extra_in, const size_t extra_in_len, const uint8_t *ad, const size_t ad_len) { AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state; if (!tls_ctx->cipher_ctx.encrypt) { // Unlike a normal AEAD, a TLS AEAD may only be used in one direction. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); return 0; } if (in_len > INT_MAX) { // EVP_CIPHER takes int as input. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); return 0; } if (max_out_tag_len < aead_tls_tag_len(ctx, in_len, extra_in_len)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); return 0; } if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); return 0; } if (ad_len != 13 - 2 /* length bytes */) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); return 0; } // To allow for CBC mode which changes cipher length, |ad| doesn't include the // length for legacy ciphers. uint8_t ad_extra[2]; ad_extra[0] = (uint8_t)(in_len >> 8); ad_extra[1] = (uint8_t)(in_len & 0xff); // Compute the MAC. This must be first in case the operation is being done // in-place. uint8_t mac[EVP_MAX_MD_SIZE]; unsigned mac_len; if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || !HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) || !HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) || !HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) || !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) { return 0; } // Configure the explicit IV. if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && !tls_ctx->implicit_iv && !EVP_EncryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) { return 0; } // Encrypt the input. int len; if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, (int)in_len)) { return 0; } unsigned block_size = EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx); // Feed the MAC into the cipher in two steps. First complete the final partial // block from encrypting the input and split the result between |out| and // |out_tag|. Then feed the rest. const size_t early_mac_len = (block_size - (in_len % block_size) % block_size); if (early_mac_len != 0) { assert(len + block_size - early_mac_len == in_len); uint8_t buf[EVP_MAX_BLOCK_LENGTH]; int buf_len; if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, buf, &buf_len, mac, (int)early_mac_len)) { return 0; } assert(buf_len == (int)block_size); OPENSSL_memcpy(out + len, buf, block_size - early_mac_len); OPENSSL_memcpy(out_tag, buf + block_size - early_mac_len, early_mac_len); } size_t tag_len = early_mac_len; if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out_tag + tag_len, &len, mac + tag_len, mac_len - tag_len)) { return 0; } tag_len += len; if (block_size > 1) { assert(block_size <= 256); assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE); // Compute padding and feed that into the cipher. uint8_t padding[256]; unsigned padding_len = block_size - ((in_len + mac_len) % block_size); OPENSSL_memset(padding, padding_len - 1, padding_len); if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out_tag + tag_len, &len, padding, (int)padding_len)) { return 0; } tag_len += len; } if (!EVP_EncryptFinal_ex(&tls_ctx->cipher_ctx, out_tag + tag_len, &len)) { return 0; } assert(len == 0); // Padding is explicit. assert(tag_len == aead_tls_tag_len(ctx, in_len, extra_in_len)); *out_tag_len = tag_len; return 1; }
BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; BIGNUM *ret = NULL; int sign; if ((a->flags & BN_FLG_CONSTTIME) != 0 || (n->flags & BN_FLG_CONSTTIME) != 0) { return BN_mod_inverse_no_branch(out, a, n, ctx); } BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) { goto err; } if (out == NULL) { R = BN_new(); } else { R = out; } if (R == NULL) { goto err; } BN_zero(Y); if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) { goto err; } A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { if (!BN_nnmod(B, B, A, ctx)) { goto err; } } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) { /* Binary inversion algorithm; requires odd modulus. * This is faster than the general algorithm if the modulus * is sufficiently small (about 400 .. 500 bits on 32-bit * sytems, but much more on 64-bit systems) */ int shift; while (!BN_is_zero(B)) { /* 0 < B < |n|, * 0 < A <= |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|) */ /* Now divide B by the maximum possible power of two in the integers, * and divide X by the same value mod |n|. * When we're done, (1) still holds. */ shift = 0; while (!BN_is_bit_set(B, shift)) { /* note that 0 < B */ shift++; if (BN_is_odd(X)) { if (!BN_uadd(X, X, n)) { goto err; } } /* now X is even, so we can easily divide it by two */ if (!BN_rshift1(X, X)) { goto err; } } if (shift > 0) { if (!BN_rshift(B, B, shift)) { goto err; } } /* Same for A and Y. Afterwards, (2) still holds. */ shift = 0; while (!BN_is_bit_set(A, shift)) { /* note that 0 < A */ shift++; if (BN_is_odd(Y)) { if (!BN_uadd(Y, Y, n)) { goto err; } } /* now Y is even */ if (!BN_rshift1(Y, Y)) { goto err; } } if (shift > 0) { if (!BN_rshift(A, A, shift)) { goto err; } } /* We still have (1) and (2). * Both A and B are odd. * The following computations ensure that * * 0 <= B < |n|, * 0 < A < |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|), * * and that either A or B is even in the next iteration. */ if (BN_ucmp(B, A) >= 0) { /* -sign*(X + Y)*a == B - A (mod |n|) */ if (!BN_uadd(X, X, Y)) { goto err; } /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that * actually makes the algorithm slower */ if (!BN_usub(B, B, A)) { goto err; } } else { /* sign*(X + Y)*a == A - B (mod |n|) */ if (!BN_uadd(Y, Y, X)) { goto err; } /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ if (!BN_usub(A, A, B)) { goto err; } } } } else { /* general inversion algorithm */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* (D, M) := (A/B, A%B) ... */ if (BN_num_bits(A) == BN_num_bits(B)) { if (!BN_one(D)) { goto err; } if (!BN_sub(M, A, B)) { goto err; } } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { /* A/B is 1, 2, or 3 */ if (!BN_lshift1(T, B)) { goto err; } if (BN_ucmp(A, T) < 0) { /* A < 2*B, so D=1 */ if (!BN_one(D)) { goto err; } if (!BN_sub(M, A, B)) { goto err; } } else { /* A >= 2*B, so D=2 or D=3 */ if (!BN_sub(M, A, T)) { goto err; } if (!BN_add(D, T, B)) { goto err; /* use D (:= 3*B) as temp */ } if (BN_ucmp(A, D) < 0) { /* A < 3*B, so D=2 */ if (!BN_set_word(D, 2)) { goto err; } /* M (= A - 2*B) already has the correct value */ } else { /* only D=3 remains */ if (!BN_set_word(D, 3)) { goto err; } /* currently M = A - 2*B, but we need M = A - 3*B */ if (!BN_sub(M, M, B)) { goto err; } } } } else { if (!BN_div(D, M, A, B, ctx)) { goto err; } } /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp = A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A = B; B = M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ /* most of the time D is very small, so we can optimize tmp := D*X+Y */ if (BN_is_one(D)) { if (!BN_add(tmp, X, Y)) { goto err; } } else { if (BN_is_word(D, 2)) { if (!BN_lshift1(tmp, X)) { goto err; } } else if (BN_is_word(D, 4)) { if (!BN_lshift(tmp, X, 2)) { goto err; } } else if (D->top == 1) { if (!BN_copy(tmp, X)) { goto err; } if (!BN_mul_word(tmp, D->d[0])) { goto err; } } else { if (!BN_mul(tmp, D, X, ctx)) { goto err; } } if (!BN_add(tmp, tmp, Y)) { goto err; } } M = Y; /* keep the BIGNUM object, the value does not matter */ Y = X; X = tmp; sign = -sign; } } /* The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y, n, Y)) { goto err; } } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y, n) < 0) { if (!BN_copy(R, Y)) { goto err; } } else { if (!BN_nnmod(R, Y, n, ctx)) { goto err; } } } else { OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); goto err; } ret = R; err: if (ret == NULL && out == NULL) { BN_free(R); } BN_CTX_end(ctx); return ret; }