Exemple #1
0
/* 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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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 {
Exemple #5
0
/* 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;
}
Exemple #6
0
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);
	}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
/* 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;
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #15
0
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;
}
Exemple #16
0
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);
}
Exemple #17
0
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;
}
Exemple #18
0
/* 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;
}
Exemple #19
0
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;
}
Exemple #20
0
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;
}
Exemple #22
0
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);
}
Exemple #23
0
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;
}
Exemple #24
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);
}
Exemple #25
0
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;
}
Exemple #26
0
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;

	}
Exemple #27
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;
}
Exemple #28
0
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;
}
Exemple #29
0
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;
}
Exemple #30
0
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;
}