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); }
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); }
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); }
// dump_payload: print out the payload from a KSSL operation in hex void dump_payload(int l, BYTE *p) { kssl_operation request; if (!debug) return; if (l > 0) { int i; printf(" Payload Raw: "); for (i = 0; i < l; ++i) { if ((i != 0) && (i%16 == 0)) { printf("\n "); } printf("%02x ", p[i]); } printf("\n"); } parse_message_payload(p, l, &request); dump_request(&request); }
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); }
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); }
// 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; }