END_TEST /******************************************************************************* * unwrap */ START_TEST(test_asn1_unwrap) { chunk_t c0 = chunk_from_chars(0x30); chunk_t c1 = chunk_from_chars(0x30, 0x01, 0xaa); chunk_t c2 = chunk_from_chars(0x30, 0x80); chunk_t c3 = chunk_from_chars(0x30, 0x81); chunk_t c4 = chunk_from_chars(0x30, 0x81, 0x01, 0xaa); chunk_t c5 = chunk_from_chars(0x30, 0x81, 0x02, 0xaa); chunk_t inner; chunk_t inner_ref = chunk_from_chars(0xaa); ck_assert(asn1_unwrap(&c0, &inner) == ASN1_INVALID); ck_assert(asn1_unwrap(&c1, &inner) == ASN1_SEQUENCE); ck_assert(chunk_equals(inner, inner_ref)); ck_assert(asn1_unwrap(&c2, &inner) == ASN1_INVALID); ck_assert(asn1_unwrap(&c3, &inner) == ASN1_INVALID); ck_assert(asn1_unwrap(&c4, &inner) == ASN1_SEQUENCE); ck_assert(chunk_equals(inner, inner_ref)); ck_assert(asn1_unwrap(&c5, &inner) == ASN1_INVALID); }
END_TEST START_TEST(test_extract_buf) { bio_writer_t *writer; chunk_t data1, data2; writer = bio_writer_create(0); writer->write_uint8(writer, 1); data1 = writer->extract_buf(writer); ck_assert_int_eq(data1.len, 1); ck_assert(data1.ptr[0] == 1); data2 = writer->get_buf(writer); ck_assert_int_eq(data2.len, 0); ck_assert(data2.ptr == NULL); data2 = writer->extract_buf(writer); ck_assert_int_eq(data2.len, 0); ck_assert(data2.ptr == NULL); writer->write_uint8(writer, 1); data2 = writer->get_buf(writer); ck_assert(chunk_equals(data1, data2)); ck_assert(data1.ptr != data2.ptr); writer->destroy(writer); chunk_free(&data1); }
END_TEST START_TEST(test_skip) { chunk_t skipped, buf, data = chunk_from_chars(0x00, 0x01, 0x02); bio_writer_t *writer; writer = bio_writer_create(4); skipped = writer->skip(writer, 3); ck_assert_int_eq(skipped.len, 3); buf = writer->get_buf(writer); ck_assert(skipped.ptr == buf.ptr); memset(skipped.ptr, 0, skipped.len); writer->write_data(writer, data); buf = writer->get_buf(writer); ck_assert(chunk_equals(buf, chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x01, 0x02))); writer->destroy(writer); writer = bio_writer_create(1); skipped = writer->skip(writer, 3); memcpy(skipped.ptr, data.ptr, data.len); writer->write_data(writer, data); assert_writer_after_write(writer, 2); writer->destroy(writer); }
/** * ipsec pool --add - add a new pool */ static void add(char *name, host_t *start, host_t *end, int timeout) { chunk_t start_addr, end_addr, cur_addr; u_int id, count; start_addr = start->get_address(start); end_addr = end->get_address(end); cur_addr = chunk_clonea(start_addr); count = get_pool_size(start_addr, end_addr); if (start_addr.len != end_addr.len || memcmp(start_addr.ptr, end_addr.ptr, start_addr.len) > 0) { fprintf(stderr, "invalid start/end pair specified.\n"); exit(EXIT_FAILURE); } id = create_pool(name, start_addr, end_addr, timeout); printf("allocating %d addresses... ", count); fflush(stdout); db->transaction(db, FALSE); while (TRUE) { db->execute(db, NULL, "INSERT INTO addresses (pool, address, identity, acquired, released) " "VALUES (?, ?, ?, ?, ?)", DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1); if (chunk_equals(cur_addr, end_addr)) { break; } chunk_increment(cur_addr); } db->commit(db); printf("done.\n"); }
END_TEST /******************************************************************************* * chunk_create_cat */ START_TEST(test_chunk_create_cat) { chunk_t foo, bar; chunk_t a, b, c; u_char *ptra, *ptrb; foo = chunk_from_str("foo"); bar = chunk_from_str("bar"); /* to simplify things we use the chunk_cata macro */ a = chunk_empty; b = chunk_empty; c = chunk_cata("cc", a, b); ck_assert_int_eq(c.len, 0); ck_assert(c.ptr != NULL); a = foo; b = bar; c = chunk_cata("cc", a, b); ck_assert_int_eq(c.len, 6); ck_assert(chunk_equals(c, chunk_from_str("foobar"))); a = chunk_clone(foo); b = chunk_clone(bar); c = chunk_cata("mm", a, b); ck_assert_int_eq(c.len, 6); ck_assert(chunk_equals(c, chunk_from_str("foobar"))); a = chunk_clone(foo); b = chunk_clone(bar); ptra = a.ptr; ptrb = b.ptr; c = chunk_cata("ss", a, b); ck_assert_int_eq(c.len, 6); ck_assert(chunk_equals(c, chunk_from_str("foobar"))); /* check memory area of cleared chunk */ ck_assert(!chunk_equals(foo, chunk_create(ptra, 3))); ck_assert(!chunk_equals(bar, chunk_create(ptrb, 3))); }
END_TEST /******************************************************************************* * integer */ START_TEST(test_asn1_integer) { typedef struct { chunk_t b; chunk_t c; } testdata_t; chunk_t b0 = chunk_from_chars(0x02, 0x01, 0x00); chunk_t b1 = chunk_from_chars(0x02, 0x01, 0x7f); chunk_t b2 = chunk_from_chars(0x02, 0x02, 0x00, 0x80); chunk_t c0 = chunk_empty; chunk_t c1 = chunk_from_chars(0x7f); chunk_t c2 = chunk_from_chars(0x80); chunk_t c3 = chunk_from_chars(0x00, 0x80); testdata_t test[] = { { b0, c0 }, { b1, c1 }, { b2, c2 }, { b2, c3 } }; chunk_t a = chunk_empty; int i; for (i = 0; i < countof(test); i++) { a = asn1_integer("c", test[i].c); ck_assert(chunk_equals(a, test[i].b)); chunk_free(&a); a = asn1_integer("m", chunk_clone(test[i].c)); ck_assert(chunk_equals(a, test[i].b)); chunk_free(&a); } }
END_TEST START_TEST(test_chunk_skip_zero) { chunk_t foobar, a; a = chunk_empty; a = chunk_skip_zero(a); assert_chunk_empty(a); foobar = chunk_from_str("foobar"); a = foobar; a = chunk_skip_zero(a); ck_assert(chunk_equals(a, foobar)); a = chunk_from_chars(0x00, 0xaa, 0xbb, 0xcc); a = chunk_skip_zero(a); ck_assert(chunk_equals(a, chunk_from_chars(0xaa, 0xbb, 0xcc))); a = chunk_skip_zero(a); ck_assert(chunk_equals(a, chunk_from_chars(0xaa, 0xbb, 0xcc))); }
END_TEST /******************************************************************************* * bitstring */ START_TEST(test_asn1_bitstring) { chunk_t a = chunk_empty; chunk_t b = chunk_from_chars(0x03, 0x05, 0x00, 0xa1, 0xa2, 0xa3, 0xa4); chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4); chunk_t d = chunk_clone(c); a = asn1_bitstring("c", c); ck_assert(chunk_equals(a, b)); chunk_free(&a); a = asn1_bitstring("m", d); ck_assert(chunk_equals(a, b)); chunk_free(&a); }
END_TEST START_TEST(test_printable_sanitize) { chunk_t sane, expected; bool printable; printable = chunk_printable(printable_data[_i].in, &sane, '?'); ck_assert(printable == printable_data[_i].printable); expected = chunk_from_str(printable_data[_i].out); ck_assert(chunk_equals(sane, expected)); chunk_free(&sane); }
END_TEST /******************************************************************************* * host_create_from_string */ static void verify_address(host_t *host, chunk_t addr, int family, uint16_t port) { ck_assert(chunk_equals(host->get_address(host), addr)); ck_assert(!host->is_anyaddr(host)); ck_assert_int_eq(host->get_port(host), port); ck_assert_int_eq(host->get_family(host), family); }
END_TEST /******************************************************************************* * test for chunk_map and friends */ START_TEST(test_chunk_map) { chunk_t *map, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); char *path = "/tmp/strongswan-chunk-map-test"; ck_assert(chunk_write(contents, path, 022, TRUE)); /* read */ map = chunk_map(path, FALSE); ck_assert(map != NULL); ck_assert_msg(chunk_equals(*map, contents), "%B", map); /* altering mapped chunk should not hurt */ *map = chunk_empty; ck_assert(chunk_unmap(map)); /* write */ map = chunk_map(path, TRUE); ck_assert(map != NULL); ck_assert_msg(chunk_equals(*map, contents), "%B", map); map->ptr[0] = 0x06; ck_assert(chunk_unmap(map)); /* verify write */ contents.ptr[0] = 0x06; map = chunk_map(path, FALSE); ck_assert(map != NULL); ck_assert_msg(chunk_equals(*map, contents), "%B", map); ck_assert(chunk_unmap(map)); unlink(path); }
END_TEST /******************************************************************************* * parse_algorithm_identifier */ START_TEST(test_asn1_parse_algorithmIdentifier) { typedef struct { int alg; bool empty; chunk_t parameters; } testdata_t; testdata_t test[] = { { OID_ECDSA_WITH_SHA1, TRUE, chunk_empty }, { OID_SHA1_WITH_RSA, TRUE, chunk_from_chars(0x05, 0x00) }, { OID_3DES_EDE_CBC, FALSE, chunk_from_chars(0x04, 0x01, 0xaa) }, { OID_PBKDF2, FALSE, chunk_from_chars(0x30, 0x01, 0xaa) } }; chunk_t algid, parameters; int i, alg; for (i = 0; i < countof(test); i++) { algid = asn1_wrap(ASN1_SEQUENCE, "mc", asn1_build_known_oid(test[i].alg), test[i].parameters); parameters = chunk_empty; if (i == 2) { alg = asn1_parse_algorithmIdentifier(algid, 0, NULL); } else { alg = asn1_parse_algorithmIdentifier(algid, 0, ¶meters); if (test[i].empty) { ck_assert(parameters.len == 0 && parameters.ptr == NULL); } else { ck_assert(chunk_equals(parameters, test[i].parameters)); } } ck_assert(alg == test[i].alg); chunk_free(&algid); } }
END_TEST START_TEST(test_chunk_from_fd_skt) { chunk_t in, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); int s[2]; ck_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0); ck_assert(write(s[1], contents.ptr, contents.len) == contents.len); close(s[1]); ck_assert_msg(chunk_from_fd(s[0], &in), "%s", strerror(errno)); close(s[0]); ck_assert_msg(chunk_equals(in, contents), "%B", &in); free(in.ptr); }
END_TEST /******************************************************************************* * memxor */ static void do_memxor(chunk_t a, chunk_t b, chunk_t exp) { chunk_t dst; dst = chunk_clonea(a); dst.len = b.len; memxor(dst.ptr, b.ptr, b.len); ck_assert(chunk_equals(dst, exp)); }
END_TEST /******************************************************************************* * simple_object */ START_TEST(test_asn1_simple_object) { chunk_t a = chunk_empty; chunk_t b = chunk_from_chars(0x04, 0x05, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5); chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4, 0xa5); a = asn1_simple_object(0x04, c); ck_assert(chunk_equals(a, b)); chunk_free(&a); }
END_TEST /******************************************************************************* * read data */ static inline void assert_reader_after_read(bio_reader_t *reader, chunk_t data) { chunk_t peek; ck_assert_int_eq(reader->remaining(reader), data.len); peek = reader->peek(reader); ck_assert_int_eq(reader->remaining(reader), data.len); ck_assert(peek.ptr == data.ptr); data.ptr != NULL ? ck_assert(chunk_equals(peek, data)) : ck_assert(peek.ptr == NULL); }
err_t scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data, scep_attributes_t *attrs, certificate_t *signer_cert) { chunk_t attributes; if (!pkcs7_parse_signedData(response, data, NULL, &attributes, signer_cert)) { return "error parsing the scep response"; } if (!parse_attributes(attributes, attrs)) { return "error parsing the scep response attributes"; } if (!chunk_equals(transID, attrs->transID)) { return "transaction ID of scep response does not match"; } return NULL; }
END_TEST /******************************************************************************* * from_time */ START_TEST(test_asn1_from_time) { typedef struct { time_t time; u_int8_t type; chunk_t chunk; } testdata_t; testdata_t test[] = { { 352984, 0x18, chunk_from_chars( 0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) }, { 352984, 0x17, chunk_from_chars( 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) }, { 1078099200, 0x17, chunk_from_chars( 0x17, 0x0d, 0x30, 0x34, 0x30, 0x33, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a) }, { 4107542400UL, 0x18, chunk_from_chars( 0x18, 0x0f, 0x32, 0x31, 0x30, 0x30, 0x30, 0x33, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a) } }; int i; chunk_t chunk; for (i = 0; i < countof(test); i++) { if (sizeof(time_t) == 4 && test[i].time < 0) { continue; } chunk = asn1_from_time(&test[i].time, test[i].type); ck_assert(chunk_equals(chunk, test[i].chunk)); free(chunk.ptr); } }
err_t scep_parse_response(chunk_t response, chunk_t transID, pkcs7_t **data, scep_attributes_t *attrs, certificate_t *signer_cert) { pkcs7_t *pkcs7; pkcs7 = pkcs7_create_from_chunk(response, 0); if (!pkcs7 || !pkcs7->parse_signedData(pkcs7, signer_cert)) { DESTROY_IF(pkcs7); return "error parsing the scep response"; } extract_attributes(pkcs7, attrs); if (!chunk_equals(transID, attrs->transID)) { pkcs7->destroy(pkcs7); return "transaction ID of scep response does not match"; } *data = pkcs7; return NULL; }
END_TEST /******************************************************************************* * test data extraction */ START_TEST(test_get_buf) { bio_writer_t *writer; chunk_t data1, data2; writer = bio_writer_create(0); writer->write_uint8(writer, 1); data1 = writer->get_buf(writer); ck_assert_int_eq(data1.len, 1); ck_assert(data1.ptr[0] == 1); data2 = writer->get_buf(writer); ck_assert(chunk_equals(data1, data2)); ck_assert(data1.ptr == data2.ptr); writer->destroy(writer); }
END_TEST START_TEST(test_newhope_ke_wrong) { chunk_t i_msg, r_msg, i_shared_secret, r_shared_secret; diffie_hellman_t *i_nh, *r_nh; i_nh = lib->crypto->create_dh(lib->crypto, NH_128_BIT); ck_assert(i_nh != NULL); ck_assert(i_nh->get_my_public_value(i_nh, &i_msg)); r_nh = lib->crypto->create_dh(lib->crypto, NH_128_BIT); ck_assert(r_nh != NULL); ck_assert(r_nh->set_other_public_value(r_nh, i_msg)); ck_assert(r_nh->get_my_public_value(r_nh, &r_msg)); /* destroy 1st instance of i_nh */ i_nh->destroy(i_nh); chunk_free(&i_msg); /* create 2nd instance of i_nh */ i_nh = lib->crypto->create_dh(lib->crypto, NH_128_BIT); ck_assert(i_nh != NULL); ck_assert(i_nh->get_my_public_value(i_nh, &i_msg)); ck_assert(i_nh->set_other_public_value(i_nh, r_msg)); ck_assert(r_nh->get_shared_secret(r_nh, &r_shared_secret)); ck_assert(i_nh->get_shared_secret(i_nh, &i_shared_secret)); ck_assert(!chunk_equals(i_shared_secret, r_shared_secret)); /* cleanup */ chunk_clear(&i_shared_secret); chunk_clear(&r_shared_secret); chunk_free(&i_msg); chunk_free(&r_msg); i_nh->destroy(i_nh); r_nh->destroy(r_nh); }
END_TEST /******************************************************************************* * build_known_oid */ START_TEST(test_asn1_build_known_oid) { typedef struct { int n; chunk_t oid; } testdata_t; testdata_t test[] = { { OID_UNKNOWN, chunk_empty }, { OID_MAX, chunk_empty }, { OID_COUNTRY, chunk_from_chars(0x06, 0x03, 0x55, 0x04, 0x06) }, { OID_STRONGSWAN, chunk_from_chars(0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa0, 0x2a, 0x01) } }; int i; chunk_t oid = chunk_empty; for (i = 0; i < countof(test); i++) { oid = asn1_build_known_oid(test[i].n); if (test[i].oid.len == 0) { ck_assert(oid.len == 0 && oid.ptr == NULL); } else { ck_assert(chunk_equals(oid, test[i].oid)); chunk_free(&oid); } } }
END_TEST /******************************************************************************* * test for chunk_from_fd */ START_TEST(test_chunk_from_fd_file) { chunk_t in, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); char *path = "/tmp/strongswan-chunk-fd-test"; int fd; ck_assert(chunk_write(contents, path, 022, TRUE)); fd = open(path, O_RDONLY); ck_assert(fd != -1); ck_assert(chunk_from_fd(fd, &in)); close(fd); ck_assert_msg(chunk_equals(in, contents), "%B", &in); unlink(path); free(in.ptr); }
/******************************************************************************* * sqlite simple test ******************************************************************************/ bool test_sqlite() { database_t *db; char *txt = "I'm a superduper test"; chunk_t data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08); int row; chunk_t qdata; char *qtxt; bool good = FALSE; enumerator_t *enumerator; db = lib->db->create(lib->db, "sqlite://" DBFILE); if (!db) { return FALSE; } if (db->execute(db, NULL, "CREATE TABLE test (txt TEXT, data BLOB)") < 0) { return FALSE; } if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)", DB_TEXT, txt, DB_BLOB, data) < 0) { return FALSE; } if (row != 1) { return FALSE; } enumerator = db->query(db, "SELECT txt, data FROM test WHERE oid = ?", DB_INT, row, DB_TEXT, DB_BLOB); if (!enumerator) { return FALSE; } while (enumerator->enumerate(enumerator, &qtxt, &qdata)) { if (good) { /* only one row */ good = FALSE; break; } if (streq(qtxt, txt) && chunk_equals(data, qdata)) { good = TRUE; } } enumerator->destroy(enumerator); if (!good) { return FALSE; } if (db->execute(db, NULL, "DELETE FROM test WHERE oid = ?", DB_INT, row) != 1) { return FALSE; } if (db->execute(db, NULL, "DROP TABLE test") < 0) { return FALSE; } db->destroy(db); unlink(DBFILE); return TRUE; }
bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, imv_state_t *state, pts_meas_algorithms_t supported_algorithms, pts_dh_group_t supported_dh_groups, pts_database_t *pts_db, credential_manager_t *pts_credmgr) { imv_session_t *session; imv_attestation_state_t *attestation_state; pen_type_t attr_type; pts_t *pts; session = state->get_session(state); attestation_state = (imv_attestation_state_t*)state; pts = attestation_state->get_pts(attestation_state); attr_type = attr->get_type(attr); switch (attr_type.type) { case TCG_PTS_PROTO_CAPS: { tcg_pts_attr_proto_caps_t *attr_cast; pts_proto_caps_flag_t flags; attr_cast = (tcg_pts_attr_proto_caps_t*)attr; flags = attr_cast->get_flags(attr_cast); pts->set_proto_caps(pts, flags); break; } case TCG_PTS_MEAS_ALGO_SELECTION: { tcg_pts_attr_meas_algo_t *attr_cast; pts_meas_algorithms_t selected_algorithm; attr_cast = (tcg_pts_attr_meas_algo_t*)attr; selected_algorithm = attr_cast->get_algorithms(attr_cast); if (!(selected_algorithm & supported_algorithms)) { DBG1(DBG_IMV, "PTS-IMC selected unsupported" " measurement algorithm"); return FALSE; } pts->set_meas_algorithm(pts, selected_algorithm); state->set_action_flags(state, IMV_ATTESTATION_ALGO); break; } case TCG_PTS_DH_NONCE_PARAMS_RESP: { tcg_pts_attr_dh_nonce_params_resp_t *attr_cast; int nonce_len, min_nonce_len; pts_dh_group_t dh_group; pts_meas_algorithms_t offered_algorithms, selected_algorithm; chunk_t responder_value, responder_nonce; attr_cast = (tcg_pts_attr_dh_nonce_params_resp_t*)attr; responder_nonce = attr_cast->get_responder_nonce(attr_cast); /* check compliance of responder nonce length */ min_nonce_len = lib->settings->get_int(lib->settings, "%s.plugins.imv-attestation.min_nonce_len", 0, lib->ns); nonce_len = responder_nonce.len; if (nonce_len < PTS_MIN_NONCE_LEN || (min_nonce_len > 0 && nonce_len < min_nonce_len)) { attr = pts_dh_nonce_error_create( max(PTS_MIN_NONCE_LEN, min_nonce_len), PTS_MAX_NONCE_LEN); out_msg->add_attribute(out_msg, attr); break; } dh_group = attr_cast->get_dh_group(attr_cast); if (!(dh_group & supported_dh_groups)) { DBG1(DBG_IMV, "PTS-IMC selected unsupported DH group"); return FALSE; } offered_algorithms = attr_cast->get_hash_algo_set(attr_cast); selected_algorithm = pts_meas_algo_select(supported_algorithms, offered_algorithms); if (selected_algorithm == PTS_MEAS_ALGO_NONE) { attr = pts_hash_alg_error_create(supported_algorithms); out_msg->add_attribute(out_msg, attr); break; } pts->set_dh_hash_algorithm(pts, selected_algorithm); if (!pts->create_dh_nonce(pts, dh_group, nonce_len)) { return FALSE; } responder_value = attr_cast->get_responder_value(attr_cast); pts->set_peer_public_value(pts, responder_value, responder_nonce); /* Calculate secret assessment value */ if (!pts->calculate_secret(pts)) { return FALSE; } state->set_action_flags(state, IMV_ATTESTATION_DH_NONCE); break; } case TCG_PTS_TPM_VERSION_INFO: { tcg_pts_attr_tpm_version_info_t *attr_cast; chunk_t tpm_version_info; attr_cast = (tcg_pts_attr_tpm_version_info_t*)attr; tpm_version_info = attr_cast->get_tpm_version_info(attr_cast); pts->set_tpm_version_info(pts, tpm_version_info); break; } case TCG_PTS_AIK: { tcg_pts_attr_aik_t *attr_cast; certificate_t *aik, *issuer; public_key_t *public; chunk_t keyid, keyid_hex, device_id; int aik_id; enumerator_t *e; bool trusted = FALSE, trusted_chain = FALSE; attr_cast = (tcg_pts_attr_aik_t*)attr; aik = attr_cast->get_aik(attr_cast); if (!aik) { DBG1(DBG_IMV, "AIK unavailable"); attestation_state->set_measurement_error(attestation_state, IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK); break; } /* check trust into public key as stored in the database */ public = aik->get_public_key(aik); public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid); DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid); keyid_hex = chunk_to_hex(keyid, NULL, FALSE); if (session->get_device_id(session, &device_id) && chunk_equals(keyid_hex, device_id)) { trusted = session->get_device_trust(session); } else { DBG1(DBG_IMV, "device ID unknown or different from AIK keyid"); } DBG1(DBG_IMV, "AIK public key is %strusted", trusted ? "" : "not "); public->destroy(public);
static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) { imv_msg_t *out_msg; imv_os_state_t *os_state; enumerator_t *enumerator; pa_tnc_attr_t *attr; pen_type_t type; TNC_Result result; chunk_t os_name = chunk_empty; chunk_t os_version = chunk_empty; bool fatal_error = FALSE, assessment = FALSE; char non_market_apps_str[] = "install_non_market_apps"; char android_id_str[] = "android_id"; char machine_id_str[] = "/var/lib/dbus/machine-id"; os_state = (imv_os_state_t*)state; /* parse received PA-TNC message and handle local and remote errors */ result = in_msg->receive(in_msg, &fatal_error); if (result != TNC_RESULT_SUCCESS) { return result; } out_msg = imv_msg_create_as_reply(in_msg); /* analyze PA-TNC attributes */ enumerator = in_msg->create_attribute_enumerator(in_msg); while (enumerator->enumerate(enumerator, &attr)) { type = attr->get_type(attr); if (type.vendor_id == PEN_IETF) { switch (type.type) { case IETF_ATTR_PRODUCT_INFORMATION: { ietf_attr_product_info_t *attr_cast; pen_t vendor_id; attr_cast = (ietf_attr_product_info_t*)attr; os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL); if (vendor_id != PEN_IETF) { DBG1(DBG_IMV, "operating system name is '%.*s' " "from vendor %N", os_name.len, os_name.ptr, pen_names, vendor_id); } else { DBG1(DBG_IMV, "operating system name is '%.*s'", os_name.len, os_name.ptr); } break; } case IETF_ATTR_STRING_VERSION: { ietf_attr_string_version_t *attr_cast; attr_cast = (ietf_attr_string_version_t*)attr; os_version = attr_cast->get_version(attr_cast, NULL, NULL); if (os_version.len) { DBG1(DBG_IMV, "operating system version is '%.*s'", os_version.len, os_version.ptr); } break; } case IETF_ATTR_NUMERIC_VERSION: { ietf_attr_numeric_version_t *attr_cast; u_int32_t major, minor; attr_cast = (ietf_attr_numeric_version_t*)attr; attr_cast->get_version(attr_cast, &major, &minor); DBG1(DBG_IMV, "operating system numeric version is %d.%d", major, minor); break; } case IETF_ATTR_OPERATIONAL_STATUS: { ietf_attr_op_status_t *attr_cast; op_status_t op_status; op_result_t op_result; time_t last_boot; attr_cast = (ietf_attr_op_status_t*)attr; op_status = attr_cast->get_status(attr_cast); op_result = attr_cast->get_result(attr_cast); last_boot = attr_cast->get_last_use(attr_cast); DBG1(DBG_IMV, "operational status: %N, result: %N", op_status_names, op_status, op_result_names, op_result); DBG1(DBG_IMV, "last boot: %T", &last_boot, TRUE); break; } case IETF_ATTR_FORWARDING_ENABLED: { ietf_attr_fwd_enabled_t *attr_cast; os_fwd_status_t fwd_status; attr_cast = (ietf_attr_fwd_enabled_t*)attr; fwd_status = attr_cast->get_status(attr_cast); DBG1(DBG_IMV, "IPv4 forwarding status: %N", os_fwd_status_names, fwd_status); if (fwd_status == OS_FWD_ENABLED) { os_state->set_os_settings(os_state, OS_SETTINGS_FWD_ENABLED); } break; } case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED: { ietf_attr_default_pwd_enabled_t *attr_cast; bool default_pwd_status; attr_cast = (ietf_attr_default_pwd_enabled_t*)attr; default_pwd_status = attr_cast->get_status(attr_cast); DBG1(DBG_IMV, "factory default password: %sabled", default_pwd_status ? "en":"dis"); if (default_pwd_status) { os_state->set_os_settings(os_state, OS_SETTINGS_DEFAULT_PWD_ENABLED); } break; } case IETF_ATTR_INSTALLED_PACKAGES: { ietf_attr_installed_packages_t *attr_cast; enumerator_t *e; status_t status; /* Received at least one Installed Packages attribute */ os_state->set_package_request(os_state, FALSE); if (!os_db) { break; } attr_cast = (ietf_attr_installed_packages_t*)attr; e = attr_cast->create_enumerator(attr_cast); status = os_db->check_packages(os_db, os_state, e); e->destroy(e); if (status == FAILED) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); assessment = TRUE; } break; } default: break; } } else if (type.vendor_id == PEN_ITA) { switch (type.type) { case ITA_ATTR_SETTINGS: { ita_attr_settings_t *attr_cast; enumerator_t *e; char *name; chunk_t value; attr_cast = (ita_attr_settings_t*)attr; e = attr_cast->create_enumerator(attr_cast); while (e->enumerate(e, &name, &value)) { if (streq(name, non_market_apps_str) && chunk_equals(value, chunk_from_chars('1'))) { os_state->set_os_settings(os_state, OS_SETTINGS_NON_MARKET_APPS); } else if ((streq(name, android_id_str) || streq(name, machine_id_str)) && os_db) { os_state->set_device_id(os_state, os_db->get_device_id(os_db, value)); } DBG1(DBG_IMV, "setting '%s'\n %.*s", name, value.len, value.ptr); } e->destroy(e); break; } case ITA_ATTR_START_ANGEL: os_state->set_angel_count(os_state, TRUE); break; case ITA_ATTR_STOP_ANGEL: os_state->set_angel_count(os_state, FALSE); break; default: break; } } } enumerator->destroy(enumerator); if (os_name.len && os_version.len) { os_type_t os_type; ita_attr_get_settings_t *attr_cast; /* set the OS type, name and version */ os_type = os_type_from_name(os_name); os_state->set_info(os_state,os_type, os_name, os_version); /* requesting installed packages */ os_state->set_package_request(os_state, TRUE); attr = ietf_attr_attr_request_create(PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES); out_msg->add_attribute(out_msg, attr); /* requesting Android or Linux settings */ attr = ita_attr_get_settings_create(); attr_cast = (ita_attr_get_settings_t*)attr; if (os_type == OS_TYPE_ANDROID) { attr_cast->add(attr_cast, android_id_str); attr_cast->add(attr_cast, non_market_apps_str); } else { attr_cast->add(attr_cast, machine_id_str); attr_cast->add(attr_cast, "/proc/sys/kernel/tainted"); } out_msg->add_attribute(out_msg, attr); } if (fatal_error || (os_state->get_attribute_request(os_state) && os_state->get_info(os_state, NULL, NULL, NULL) == NULL)) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); assessment = TRUE; } /* If all Installed Packages attributes were received, go to assessment */ if (!assessment && !os_state->get_package_request(os_state) && !os_state->get_angel_count(os_state) && os_state->get_info(os_state, NULL, NULL, NULL)) { int device_id, count, count_update, count_blacklist, count_ok; u_int os_settings; os_settings = os_state->get_os_settings(os_state); os_state->get_count(os_state, &count, &count_update, &count_blacklist, &count_ok); DBG1(DBG_IMV, "processed %d packages: %d not updated, %d blacklisted, " "%d ok, %d not found", count, count_update, count_blacklist, count_ok, count - count_update - count_blacklist - count_ok); /* Store device information in database */ device_id = os_state->get_device_id(os_state); if (os_db && device_id) { os_db->set_device_info(os_db, device_id, os_state->get_info(os_state, NULL, NULL, NULL), count, count_update, count_blacklist, os_settings); } if (count_update || count_blacklist || os_settings) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR); } else { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_ALLOW, TNC_IMV_EVALUATION_RESULT_COMPLIANT); } assessment = TRUE; } if (assessment) { result = out_msg->send_assessment(out_msg); out_msg->destroy(out_msg); if (result != TNC_RESULT_SUCCESS) { return result; } return imv_os->provide_recommendation(imv_os, state); } /* send PA-TNC message with excl flag set */ result = out_msg->send(out_msg, TRUE); out_msg->destroy(out_msg); return result; }
/** * Load a generic public key from an SSH key blob */ static sshkey_public_key_t *parse_public_key(chunk_t blob) { bio_reader_t *reader; chunk_t format; reader = bio_reader_create(blob); if (!reader->read_data32(reader, &format)) { DBG1(DBG_LIB, "invalid key format in SSH key"); reader->destroy(reader); return NULL; } if (chunk_equals(format, chunk_from_str("ssh-rsa"))) { chunk_t n, e; if (!reader->read_data32(reader, &e) || !reader->read_data32(reader, &n)) { DBG1(DBG_LIB, "invalid RSA key in SSH key"); reader->destroy(reader); return NULL; } reader->destroy(reader); return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); } else if (format.len > strlen(ECDSA_PREFIX) && strneq(format.ptr, ECDSA_PREFIX, strlen(ECDSA_PREFIX))) { chunk_t ec_blob, identifier, q, oid, encoded; sshkey_public_key_t *key; ec_blob = reader->peek(reader); reader->destroy(reader); reader = bio_reader_create(ec_blob); if (!reader->read_data32(reader, &identifier) || !reader->read_data32(reader, &q)) { DBG1(DBG_LIB, "invalid ECDSA key in SSH key"); reader->destroy(reader); return NULL; } oid = parse_ec_identifier(identifier); if (!oid.ptr) { DBG1(DBG_LIB, "invalid ECDSA key identifier in SSH key"); reader->destroy(reader); return NULL; } reader->destroy(reader); /* build key from subjectPublicKeyInfo */ encoded = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_EC_PUBLICKEY), oid), asn1_bitstring("c", q)); key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER, encoded, BUILD_END); chunk_free(&encoded); return key; } DBG1(DBG_LIB, "unsupported SSH key format %.*s", (int)format.len, format.ptr); reader->destroy(reader); return NULL; }
END_TEST START_TEST(test_derive_child_keys) { tkm_diffie_hellman_t *dh = tkm_diffie_hellman_create(MODP_4096_BIT); fail_if(!dh, "Unable to create DH object"); proposal_t *proposal = proposal_create_from_string(PROTO_ESP, "aes256-sha512-modp4096"); fail_if(!proposal, "Unable to create proposal"); proposal->set_spi(proposal, 42); tkm_keymat_t *keymat = tkm_keymat_create(TRUE); fail_if(!keymat, "Unable to create keymat"); chunk_t encr_i, encr_r, integ_i, integ_r; chunk_t nonce = chunk_from_chars("test chunk"); fail_unless(keymat->keymat_v2.derive_child_keys(&keymat->keymat_v2, proposal, (diffie_hellman_t *)dh, nonce, nonce, &encr_i, &integ_i, &encr_r, &integ_r), "Child key derivation failed"); esa_info_t *info = (esa_info_t *)encr_i.ptr; fail_if(!info, "encr_i does not contain esa information"); fail_if(info->isa_id != keymat->get_isa_id(keymat), "Isa context id mismatch (encr_i)"); fail_if(info->spi_r != 42, "SPI mismatch (encr_i)"); fail_unless(chunk_equals(info->nonce_i, nonce), "nonce_i mismatch (encr_i)"); fail_unless(chunk_equals(info->nonce_r, nonce), "nonce_r mismatch (encr_i)"); fail_if(info->is_encr_r, "Flag is_encr_r set for encr_i"); fail_if(info->dh_id != dh->get_id(dh), "DH context id mismatch (encr_i)"); chunk_free(&info->nonce_i); chunk_free(&info->nonce_r); info = (esa_info_t *)encr_r.ptr; fail_if(!info, "encr_r does not contain esa information"); fail_if(info->isa_id != keymat->get_isa_id(keymat), "Isa context id mismatch (encr_r)"); fail_if(info->spi_r != 42, "SPI mismatch (encr_r)"); fail_unless(chunk_equals(info->nonce_i, nonce), "nonce_i mismatch (encr_r)"); fail_unless(chunk_equals(info->nonce_r, nonce), "nonce_r mismatch (encr_r)"); fail_unless(info->is_encr_r, "Flag is_encr_r set for encr_r"); fail_if(info->dh_id != dh->get_id(dh), "DH context id mismatch (encr_i)"); chunk_free(&info->nonce_i); chunk_free(&info->nonce_r); proposal->destroy(proposal); dh->dh.destroy(&dh->dh); keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat); chunk_free(&encr_i); chunk_free(&encr_r); }
/** * Parse a PKCS#7 envelopedData object */ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data, chunk_t serialNumber, private_key_t *key) { asn1_parser_t *parser; chunk_t object; chunk_t iv = chunk_empty; chunk_t symmetric_key = chunk_empty; chunk_t encrypted_content = chunk_empty; crypter_t *crypter = NULL; int enc_alg = OID_UNKNOWN; int content_enc_alg = OID_UNKNOWN; int version; int objectID; bool success = FALSE; contentInfo_t cInfo = empty_contentInfo; *data = chunk_empty; if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) { goto failed; } if (cInfo.type != OID_PKCS7_ENVELOPED_DATA) { DBG1(DBG_LIB, "pkcs7 content type is not envelopedData"); goto failed; } parser = asn1_parser_create(envelopedDataObjects, cInfo.content); parser->set_top_level(parser, 2); while (parser->iterate(parser, &objectID, &object)) { u_int level = parser->get_level(parser); switch (objectID) { case PKCS7_ENVELOPED_VERSION: version = object.len ? (int)*object.ptr : 0; DBG2(DBG_LIB, " v%d", version); if (version != 0) { DBG1(DBG_LIB, "envelopedData version is not 0"); goto end; } break; case PKCS7_RECIPIENT_INFO_VERSION: version = object.len ? (int)*object.ptr : 0; DBG2(DBG_LIB, " v%d", version); if (version != 0) { DBG1(DBG_LIB, "recipient info version is not 0"); goto end; } break; case PKCS7_ISSUER: { identification_t *issuer = identification_create_from_encoding( ID_DER_ASN1_DN, object); DBG2(DBG_LIB, " \"%Y\"", issuer); issuer->destroy(issuer); break; } case PKCS7_SERIAL_NUMBER: if (!chunk_equals(serialNumber, object)) { DBG1(DBG_LIB, "serial numbers do not match"); goto end; } break; case PKCS7_ENCRYPTION_ALG: enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL); if (enc_alg != OID_RSA_ENCRYPTION) { DBG1(DBG_LIB, "only rsa encryption supported"); goto end; } break; case PKCS7_ENCRYPTED_KEY: if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key)) { DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa"); goto end; } DBG4(DBG_LIB, "symmetric key %B", &symmetric_key); break; case PKCS7_CONTENT_TYPE: if (asn1_known_oid(object) != OID_PKCS7_DATA) { DBG1(DBG_LIB, "encrypted content not of type pkcs7 data"); goto end; } break; case PKCS7_CONTENT_ENC_ALGORITHM: content_enc_alg = asn1_parse_algorithmIdentifier(object, level, &iv); if (content_enc_alg == OID_UNKNOWN) { DBG1(DBG_LIB, "unknown content encryption algorithm"); goto end; } if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV")) { DBG1(DBG_LIB, "IV could not be parsed"); goto end; } break; case PKCS7_ENCRYPTED_CONTENT: encrypted_content = object; break; } } success = parser->success(parser); end: parser->destroy(parser); if (!success) { goto failed; } success = FALSE; /* decrypt the content */ { encryption_algorithm_t alg; size_t key_size; crypter_t *crypter; alg = encryption_algorithm_from_oid(content_enc_alg, &key_size); if (alg == ENCR_UNDEFINED) { DBG1(DBG_LIB, "unsupported content encryption algorithm"); goto failed; } crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size); if (crypter == NULL) { DBG1(DBG_LIB, "crypter %N not available", encryption_algorithm_names, alg); goto failed; } if (symmetric_key.len != crypter->get_key_size(crypter)) { DBG1(DBG_LIB, "symmetric key length %d is wrong", symmetric_key.len); goto failed; } if (iv.len != crypter->get_iv_size(crypter)) { DBG1(DBG_LIB, "IV length %d is wrong", iv.len); goto failed; } crypter->set_key(crypter, symmetric_key); crypter->decrypt(crypter, encrypted_content, iv, data); DBG4(DBG_LIB, "decrypted content with padding: %B", data); } /* remove the padding */ { u_char *pos = data->ptr + data->len - 1; u_char pattern = *pos; size_t padding = pattern; if (padding > data->len) { DBG1(DBG_LIB, "padding greater than data length"); goto failed; } data->len -= padding; while (padding-- > 0) { if (*pos-- != pattern) { DBG1(DBG_LIB, "wrong padding pattern"); goto failed; } } } success = TRUE; failed: DESTROY_IF(crypter); chunk_clear(&symmetric_key); if (!success) { free(data->ptr); } return success; }
END_TEST /******************************************************************************* * oid_from_string */ START_TEST(test_asn1_oid_from_string) { typedef struct { char *string; chunk_t oid; } testdata_t; testdata_t test[] = { { "", chunk_empty }, { " ", chunk_empty }, { "0.2.262.1", chunk_from_chars( 0x02, 0x82, 0x06, 0x01) }, { "1.2.840.10045.4.1", chunk_from_chars( 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01) }, { "1.3.6.1.4.1.36906.1", chunk_from_chars( 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa0, 0x2a, 0x01) }, { "2.16.840.1.101.3.4.2.1", chunk_from_chars( 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01) }, { "0.10.100.1000.10000.100000.1000000.10000000.100000000.268435455", chunk_from_chars(0x0a,0x64, 0x87, 0x68, 0xce, 0x10, 0x86, 0x8d, 0x20, 0xbd, 0x84, 0x40, 0x84, 0xe2, 0xad, 0x00, 0xaf, 0xd7, 0xc2, 0x00, 0xff, 0xff, 0xff, 0x7f) }, { "0.1.2.3.4.5.6.7.8.9.10.128.129.130.131.132.133.134.135.136.137." "256.257.258.259.260.261.262.263.264.265.384.385.386.387.388." "2097153", chunk_from_chars( 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x81, 0x00, 0x81, 0x01, 0x81, 0x02, 0x81, 0x03, 0x81, 0x04, 0x81, 0x05, 0x81, 0x06, 0x81, 0x07, 0x81, 0x08, 0x81, 0x09, 0x82, 0x00, 0x82, 0x01, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x06, 0x82, 0x07, 0x82, 0x08, 0x82, 0x09, 0x83, 0x00, 0x83, 0x01, 0x83, 0x02, 0x83, 0x03, 0x83, 0x04, 0x81, 0x80, 0x80, 0x01) }, { "0.1.2.3.4.5.6.7.8.9.10.128.129.130.131.132.133.134.135.136.137." "256.257.258.259.260.261.262.263.264.265.384.385.386.387.388." "1.2097153", chunk_empty }, { "1.a.2.b.3", chunk_empty } }; int i; chunk_t oid = chunk_empty; for (i = 0; i < countof(test); i++) { oid = asn1_oid_from_string(test[i].string); if (test[i].oid.len == 0) { ck_assert(oid.len == 0 && oid.ptr == NULL); } else { ck_assert(chunk_equals(oid, test[i].oid)); chunk_free(&oid); } } }