Пример #1
0
void kssl_repeat_op_ping(connection *c, int repeat)
{
    char hello[255];
    kssl_header echo1;
    kssl_operation req, resp;
    kssl_header *h;
    int i;
    BYTE *payload = malloc(255 + 1);
    test("Repeat KSSL_OP_PING %d times (%p)", repeat, c);
    echo1.version_maj = KSSL_VERSION_MAJ;
    echo1.id = 0x12345679;
    zero_operation(&req);
    req.is_opcode_set = 1;
    req.is_payload_set = 1;
    req.opcode = KSSL_OP_PING;
    req.payload_len = 255 + 1;
    req.payload = payload;
    for (i = 0; i < repeat; i++) {
        sprintf(hello, "Hello, World! %d", i);
        memcpy((char *)payload, hello, strlen(hello)+1);
        req.payload_len = strlen(hello)+1;
        h = kssl(c->ssl, &echo1, &req);
        test_assert(h->id == echo1.id);
        test_assert(h->version_maj == KSSL_VERSION_MAJ);
        parse_message_payload(h->data, h->length, &resp);
        test_assert(resp.opcode == KSSL_OP_PONG);
        test_assert(resp.payload_len == req.payload_len);
        test_assert(strncmp((char *)resp.payload, (char *)req.payload, strlen(hello)) == 0);
        free(h->data);
        free(h);
    }
    ok(0);
    free(payload);
}
Пример #2
0
void kssl_op_ping_payload(connection *c)
{
    const char *hello = "Hello, World!";
    kssl_operation req, resp;
    kssl_header echo1;
    kssl_header *h;
    BYTE *payload;
    test("KSSL_OP_PING with payload (%p)", c);

    payload = malloc(strlen(hello) + 1);
    echo1.version_maj = KSSL_VERSION_MAJ;
    echo1.id = 0x12345679;
    zero_operation(&req);
    req.is_opcode_set = 1;
    req.is_payload_set = 1;
    req.opcode = KSSL_OP_PING;
    req.payload_len = strlen(hello);
    req.payload = payload;
    memcpy((char *)payload, hello, strlen(hello));
    h = kssl(c->ssl, &echo1, &req);
    test_assert(h->id == echo1.id);
    test_assert(h->version_maj == KSSL_VERSION_MAJ);
    parse_message_payload(h->data, h->length, &resp);
    test_assert(resp.opcode == KSSL_OP_PONG);
    test_assert(resp.payload_len == req.payload_len);
    test_assert(strncmp((char *)resp.payload, (char *)req.payload, strlen(hello)) == 0);
    ok(h);
    free(payload);
}
Пример #3
0
void kssl_bad_opcode(connection *c)
{
    kssl_header bad;
    kssl_operation req, resp;
    kssl_header *h;

    test("Bad KSSL opcode (%p)", c);
    bad.version_maj = KSSL_VERSION_MAJ;
    bad.version_min = KSSL_VERSION_MIN;
    bad.id = 0x12345678;
    bad.length = 0; // to be overridden by serialization
    zero_operation(&req);
    req.is_opcode_set = 1;
    req.is_payload_set = 1;
    req.opcode = 0xBB;
    req.payload_len = 0;
    h = kssl(c->ssl, &bad, &req);
    test_assert(h->id == bad.id);
    test_assert(h->version_maj == KSSL_VERSION_MAJ);
    parse_message_payload(h->data, h->length, &resp);
    test_assert(resp.opcode == KSSL_OP_ERROR);
    test_assert(resp.payload_len == 1);
    test_assert(resp.payload[0] == KSSL_ERROR_BAD_OPCODE);
    ok(h);
}
Пример #4
0
void kssl_op_ping_bad_version(connection *c)
{
    kssl_header echo0;
    kssl_operation req, resp;
    kssl_header *h;
    test("KSSL_OP_PING with bad version (%p)", c);
    echo0.id = 0x12345678;
    echo0.version_maj = KSSL_VERSION_MAJ+1;
    zero_operation(&req);
    req.is_opcode_set = 1;
    req.is_payload_set = 1;
    req.opcode = KSSL_OP_PING;
    req.payload_len = 0;
    h = kssl(c->ssl, &echo0, &req);
    test_assert(h->version_maj == KSSL_VERSION_MAJ);
    test_assert(h->id == echo0.id);
    parse_message_payload(h->data, h->length, &resp);
    test_assert(resp.opcode == KSSL_OP_ERROR);
    test_assert(resp.payload_len == 1);
    test_assert(resp.payload[0] == KSSL_ERROR_VERSION_MISMATCH);
    ok(h);
}
Пример #5
0
void kssl_pipeline_op_ping(connection *c, int repeat)
{
    char hello[255];
    kssl_header echo1;
    kssl_operation req;
    BYTE *payload = malloc(255 + 1);

    test("Pipeline KSSL_OP_PING %d times (%p)", repeat, c);
    echo1.version_maj = KSSL_VERSION_MAJ;
    echo1.id = 0x12345679;
    zero_operation(&req);
    req.is_opcode_set = 1;
    req.is_payload_set = 1;
    req.opcode = KSSL_OP_PING;
    req.payload_len = 255 + 1;
    req.payload = payload;
    sprintf(hello, "Hello, World! Pipeline");
    memcpy((char *)payload, hello, strlen(hello)+1);
    req.payload_len = strlen(hello)+1;
    kssl_pipeline(c->ssl, &echo1, &req, repeat);
    ok(0);
    free(payload);
}
Пример #6
0
void kssl_op_error(connection *c)
{
    kssl_header echo0;
    kssl_operation req, resp;
    kssl_header *h;
    test("KSSL_OP_ERROR (%p)", c);

    echo0.version_maj = KSSL_VERSION_MAJ;
    echo0.id = 0x12345678;
    zero_operation(&req);
    req.is_opcode_set = 1;
    req.is_payload_set = 1;
    req.opcode = KSSL_OP_ERROR;
    req.payload_len = 0;
    h = kssl(c->ssl, &echo0, &req);
    test_assert(h->id == echo0.id);
    test_assert(h->version_maj == KSSL_VERSION_MAJ);
    parse_message_payload(h->data, h->length, &resp);
    test_assert(resp.opcode == KSSL_OP_ERROR);
    test_assert(resp.payload_len == 1);
    test_assert(resp.payload[0] == KSSL_ERROR_UNEXPECTED_OPCODE);
    ok(h);
}
Пример #7
0
// kssl_operate: create a serialized response from a KSSL request
// header and payload
kssl_error_code kssl_operate(kssl_header *header,
                             BYTE *payload,
                             pk_list privates,
                             BYTE **out_response,
                             int *out_response_len) {
  kssl_error_code err = KSSL_ERROR_NONE;
  BYTE *local_resp = NULL;
  int local_resp_len = 0;

  // Parse the indices of the items out of the payload
  kssl_header out_header;
  kssl_operation request;
  kssl_operation response;
  BYTE *out_payload = NULL;
  zero_operation(&request);
  zero_operation(&response);

  *out_response = 0;
  *out_response_len = 0;

  // Extract the items from the payload
  err = parse_message_payload(payload, header->length, &request);
  if (err != KSSL_ERROR_NONE) {
    goto exit;
  }

  if (silent == 0) {
    log_operation(header, &request);
  }

  switch (request.opcode) {
    // Other side sent response, error or pong: unexpected
    case KSSL_OP_RESPONSE:
    case KSSL_OP_ERROR:
    case KSSL_OP_PONG:
    {
      err = KSSL_ERROR_UNEXPECTED_OPCODE;
      break;
    }

    // Echo is trivial, it just echos the complete state->header back
    // including the payload item
    case KSSL_OP_PING:
    {
      response.is_payload_set = 1;
      response.payload = request.payload;
      response.payload_len = request.payload_len;
      response.is_opcode_set = 1;
      response.opcode = KSSL_OP_PONG;

      break;
    }

    // Decrypt or sign the payload using the private key
    case KSSL_OP_RSA_DECRYPT:
    case KSSL_OP_RSA_SIGN_MD5SHA1:
    case KSSL_OP_RSA_SIGN_SHA1:
    case KSSL_OP_RSA_SIGN_SHA224:
    case KSSL_OP_RSA_SIGN_SHA256:
    case KSSL_OP_RSA_SIGN_SHA384:
    case KSSL_OP_RSA_SIGN_SHA512:
    {
      unsigned int payload_size;
      int max_payload_size;
      int key_id;

      if (request.is_digest_set == 0) {
        err = KSSL_ERROR_FORMAT;
        break;
      }

      // Identify private key from request digest
      key_id = find_private_key(privates, request.digest);
      if (key_id < 0) {
        err = KSSL_ERROR_KEY_NOT_FOUND;
        break;
      }

      // Allocate buffer to hold output of private key operation
      max_payload_size = key_size(privates, key_id);
      out_payload = malloc(max_payload_size);
      if (out_payload == NULL) {
        err = KSSL_ERROR_INTERNAL;
        break;
      }

      // Operate on payload
      err = private_key_operation(privates, key_id, request.opcode,
          request.payload_len, request.payload, out_payload,
          &payload_size);
      if (err != KSSL_ERROR_NONE) {
        err = KSSL_ERROR_CRYPTO_FAILED;
        break;
      }

      response.is_payload_set = 1;
      response.payload        = out_payload;
      response.payload_len    = payload_size;
      response.is_opcode_set  = 1;
      response.opcode         = KSSL_OP_RESPONSE;

      break;
    }

    // This should not occur
  default:
    {
      err = KSSL_ERROR_BAD_OPCODE;
      break;
    }
  }

exit:
  if (err != KSSL_ERROR_NONE) {
    err = kssl_error(header->id, err, &local_resp, &local_resp_len);
  } else {

    // Create output header

    out_header.version_maj = KSSL_VERSION_MAJ;
    out_header.version_min = KSSL_VERSION_MIN;
    out_header.id          = header->id;

    // Note that the response in &local_resp is dynamically allocated
    // and needs to be freed

    err = flatten_operation(&out_header, &response, &local_resp,
        &local_resp_len);
  }

  if (out_payload != NULL) {
    free(out_payload);
  }

  if (err == KSSL_ERROR_NONE) {
    *out_response = local_resp;
    *out_response_len = local_resp_len;
  }

  return err;
}
Пример #8
0
// parse_message_payload: parse a message payload into a
// kssl_operation struct
kssl_error_code parse_message_payload(BYTE *payload,               //
                                      int len,                     //
                                      kssl_operation *operation) { //
    int offset = 0;
    kssl_item temp_item;
    if (payload == NULL || operation == NULL) {
        return KSSL_ERROR_INTERNAL;
    }

    zero_operation(operation);

    // Count number of items and validate structure
    while (offset < len) {
        if (len - offset < (int)(KSSL_ITEM_HEADER_SIZE)) {
            return KSSL_ERROR_FORMAT;
        }

        if (parse_item(payload, &offset, &temp_item) != KSSL_ERROR_NONE ||
                len < offset) {
            return KSSL_ERROR_FORMAT;
        }

        // Iterate through known tags, populating necessary values
        switch (temp_item.tag) {
        case KSSL_TAG_OPCODE:
        {
            // Skip over malformed tags
            if (temp_item.length != 1) {
                continue;
            }

            operation->opcode = temp_item.data[0];
            operation->is_opcode_set = 1;
            break;
        }
        case KSSL_TAG_DIGEST:
        {
            // Skip over malformed tags
            if (temp_item.length != KSSL_DIGEST_SIZE) continue;
            operation->digest = temp_item.data;
            operation->is_digest_set = 1;
            break;
        }
        case KSSL_TAG_PAYLOAD:
        {
            operation->payload_len = temp_item.length;
            operation->payload = temp_item.data;
            operation->is_payload_set = 1;
            break;
        }
        case KSSL_TAG_CLIENT_IP:
        {
            operation->ip_len = temp_item.length;
            operation->ip = temp_item.data;
            operation->is_ip_set = 1;
            break;
        }
        case KSSL_TAG_PADDING:
        {
            break;
        }
        default:
            break;
        }
    }

    // check to see if opcode and payload are set
    if (operation->is_opcode_set == 0 || operation->is_payload_set == 0) {
        return KSSL_ERROR_FORMAT;
    }

    return KSSL_ERROR_NONE;
}