/* Verifies signature for the local file DATA_FILENAME first, and on failure * downloads the signature based on DATA_URL and tries to verify again. * * returns: true if signature verification succeeded, false if verification * failed, or the signature download failed */ bool download_and_verify_signature(const char *data_url, const char *data_filename) { char *sig_url; char *sig_filename; int ret; bool result; if (!sigcheck) { return false; } string_or_die(&sig_url, "%s.sig", data_url); string_or_die(&sig_filename, "%s.sig", data_filename); // Try verifying a local copy of the signature first result = verify_signature(data_filename, sig_filename, false); if (result) { goto out; } // Else, download a fresh signature, and verify ret = swupd_curl_get_file(sig_url, sig_filename, NULL, NULL, false); if (ret == 0) { result = verify_signature(data_filename, sig_filename, true); } else { // download failed result = false; } out: free(sig_filename); free(sig_url); return result; }
void verify_page(fz_context *ctx, pdf_document *doc, int n, pdf_page *page) { pdf_widget *widget; for (widget = pdf_first_widget(ctx, page); widget; widget = pdf_next_widget(ctx, widget)) if (pdf_widget_type(ctx, widget) == PDF_WIDGET_TYPE_SIGNATURE) verify_signature(ctx, doc, n, widget); }
int main(int argc, char *argv[]) { if (argc != 2) fail("usage: sceverify filename"); ptr = mmap_file(argv[1]); type = be16(ptr + 0x0a); if (type == 1) read_self_header(); else if(type == 3) read_pkg_header(); else if(type == 4) read_spp_header(); else fail("Unknown type: %d", type); if (flags & 0x8000) fail("devkit file; nothing to verify"); if (klist == NULL) fail("no key found"); decrypt(); verify_signature(); verify_hashes(); if (did_fail) printf(" * please not that the hash will always fail for " "unaligned non-LOAD phdrs\n"); return 0; }
void inspect_key (SSL *ssl, const char *hostname) { verify_signature (ssl, hostname); check_name (ssl, hostname); }
bool PeerRequest::validate(const Lock& lock) const { bool validNym = false; if (nym_) { validNym = nym_->VerifyPseudonym(); } else { otErr << __FUNCTION__ << ": invalid nym." << std::endl; } const bool validSyntax = proto::Validate(contract(lock), VERBOSE); if (!validSyntax) { otErr << __FUNCTION__ << ": invalid syntax." << std::endl; } if (1 > signatures_.size()) { otErr << __FUNCTION__ << ": Missing signature." << std::endl; return false; } bool validSig = false; auto& signature = *signatures_.cbegin(); if (signature) { validSig = verify_signature(lock, *signature); } if (!validSig) { otErr << __FUNCTION__ << ": invalid signature." << std::endl; } return (validNym && validSyntax && validSig); }
int inline_gpg_verify(const char *content, size_t len, const char *keyring) { verify_signature(content, len, keyring, NULL); return 0; }
void inspect_key (ssl_context *ssl, const char *hostname) { verify_signature (ssl, hostname); // ssl_get_verify_result() already checks for CN / subjectAltName match // and reports the mismatch as error. So check_name() is not called }
void verify_page(fz_context *ctx, pdf_document *doc, int n, pdf_page *page) { pdf_annot *annot; for (annot = pdf_first_annot(ctx, page); annot; annot = pdf_next_annot(ctx, annot)) if (pdf_annot_type(ctx, annot) == PDF_ANNOT_WIDGET) if (pdf_widget_type(ctx, annot) == PDF_WIDGET_TYPE_SIGNATURE) verify_signature(ctx, doc, n, annot); }
bool verify_signature(const ec_uncompressed& point, const hash_digest& hash, const ec_signature& signature) { secp256k1_pubkey pubkey; const auto context = verification.context(); return parse(context, pubkey, point) && verify_signature(context, pubkey, hash, signature); }
int verify_message_signature(notary_header *hdr, RSA* pub_key) { int sig_len = ntohs(hdr->sig_len); int data_len = ntohs(hdr->total_len) - sig_len - sizeof(notary_header); char* data = (char*)(hdr + 1); unsigned char *sig = (unsigned char*) (data + data_len); DPRINTF(DEBUG_CRYPTO, "msg verify: data_len = %d sig_len = %d \n", data_len, sig_len); return verify_signature(data, data_len, pub_key, sig, sig_len); }
bool verify_update_signature(dwindow_update_signature *signature) { if (!signature) return false; unsigned char sha1[20]; SHA1Hash(sha1, ((unsigned char*)signature) + sizeof(signature->signature), sizeof(dwindow_update_signature) - sizeof(signature->signature)); return verify_signature((DWORD*)sha1, (DWORD*)signature->signature, dwindow_network_n); }
int main(int argc, char **argv) { GError *error = NULL; int retval = EXIT_SUCCESS; EVP_PKEY *pubkey; if (!process_arguments(&argc, &argv, &error)) { retval = handle_error(error); g_clear_error(&error); } else if ((pubkey = read_public_key(option_key_file, &error)) == NULL) { retval = handle_error(error); g_clear_error(&error); } else { FILE *infile = fopen(option_data_file, "rb"); if (infile == NULL) { fprintf(stderr, "%s: %s\n", option_data_file, strerror(errno)); retval = EXIT_IO_ERROR; } else { uint8_t hash[SHA256_DIGEST_LENGTH]; uint8_t signature[SIGNATURE_SIZE]; if (fread(signature, 1, sizeof(signature), infile) != sizeof(signature)) { if (ferror(infile)) { fprintf( stderr, "%s: %s\n", option_data_file, strerror(errno)); retval = EXIT_IO_ERROR; } else { fprintf(stderr, "%s: File too short for signature\n", option_data_file); retval = EXIT_FORMAT_ERROR; } } else if (!hash_stream(infile, hash, &error) || !verify_signature(hash, signature, pubkey, &error)) { retval = handle_error(error); g_clear_error(&error); } else if (option_out_file && !write_out_file(infile, option_out_file, &error)) { retval = handle_error(error); g_clear_error(&error); } fclose(infile); } EVP_PKEY_free(pubkey); } return retval; }
int sigverify_main(int argc, char *argv[]) { int opt; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int long_index = 0; while ((opt = getopt_long(argc, argv, "h", long_options, &long_index)) != -1) { switch (opt) { case 'h': sigverify_usage(stdout); return EXIT_SUCCESS; default: sigverify_usage(stderr); return EXIT_FAILURE; } } if (argc - optind != 2) { sigverify_usage(stderr); return EXIT_FAILURE; } #if COMPILE_ERROR_STRINGS ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); #endif const char *path = argv[optind]; const char *sig_path = argv[optind + 1]; SigVerifyResult result = verify_signature(path, sig_path); switch (result) { case SigVerifyResult::Valid: return EXIT_SUCCESS; case SigVerifyResult::Invalid: return EXIT_INVALID; case SigVerifyResult::Failure: default: return EXIT_FAILURE; } }
int _tmain() { const wchar_t* file_name = L"Diablo III Launcher.exe"; if (verify_signature(file_name) == true) { wprintf_s(L"The file \"%s\" is signed and the signature was verified.\n", file_name); std::wstring signer = get_signer(file_name); wprintf_s(L"%s signer is %s\n", file_name, signer.c_str()); } else { wprintf_s(L"The file \"%s\" is not trusted.\n", file_name); } return 0; }
/** * Verifies "data" against "signature". * * @return TRUE if the signature matches. */ bool svn_release_notification_verify(uint32 revision, time_t date, const struct array *signature) { char rev[12], data[64]; struct array input; uint32_to_string_buf(revision, rev, sizeof rev); input.data = (void *) data; input.size = concat_strings(data, sizeof data, "r", rev, "@", uint32_to_string(date), (void *) 0); return verify_signature(svn_release_notify_certificate(), &input, signature); }
retvalue signature_check(const struct signature_requirement *requirements, const char *releasegpg, const char *releasename, const char *releasedata, size_t releaselen) { gpg_error_t err; int gpgfd; gpgme_data_t dh, dh_gpg; assert (requirements != NULL); if (FAILEDTOALLOC(releasedata) || FAILEDTOALLOC(releasegpg)) return RET_ERROR_OOM; assert (context != NULL); /* Read the file and its signature into memory: */ gpgfd = open(releasegpg, O_RDONLY|O_NOCTTY); if (gpgfd < 0) { int e = errno; fprintf(stderr, "Error opening '%s': %s\n", releasegpg, strerror(e)); return RET_ERRNO(e); } err = gpgme_data_new_from_fd(&dh_gpg, gpgfd); if (err != 0) { (void)close(gpgfd); fprintf(stderr, "Error reading '%s':\n", releasegpg); return gpgerror(err); } err = gpgme_data_new_from_mem(&dh, releasedata, releaselen, 0); if (err != 0) { gpgme_data_release(dh_gpg); return gpgerror(err); } /* Verify the signature */ err = gpgme_op_verify(context, dh_gpg, dh, NULL); gpgme_data_release(dh_gpg); gpgme_data_release(dh); close(gpgfd); if (err != 0) { fprintf(stderr, "Error verifying '%s':\n", releasegpg); return gpgerror(err); } return verify_signature(requirements, releasegpg, releasename); }
/** * Given the file name of a signed boot image, verifies the signature * @param image_file Name of the boot image file */ static int verify(const char *image_file) { BootSignature *bs = NULL; int fd = -1; int rc = 1; off64_t offset = 0; if (!image_file) { return rc; } if ((fd = open(image_file, O_RDONLY | O_LARGEFILE)) == -1) { return rc; } if (get_signature_offset(fd, &offset) == -1) { goto out; } if (read_signature(fd, offset, &bs) == -1) { goto out; } if (validate_signature_block(bs, offset) == -1) { goto out; } if (verify_signature(fd, offset, bs) == -1) { goto out; } printf("Signature is VALID\n"); rc = 0; out: if (bs) { BootSignature_free(bs); } if (fd != -1) { close(fd); } return rc; }
static bool check_signature(const char *path, const char *sig_path) { SigVerifyResult result; result = verify_signature(path, sig_path); switch (result) { case SigVerifyResult::VALID: return true; case SigVerifyResult::INVALID: LOGE("%s: Invalid signature", path); return false; case SigVerifyResult::FAILURE: LOGE("%s: Failed to check signature", path); return false; default: assert(false); return false; } }
static bool process_hunk(char const *program, struct notify_info *notify, struct memory_block_data const *payload, struct memory_block_signature const *signature) { struct signature_algorithm *sigalg = NULL; struct decompression_algorithm *decompalg = NULL; sigalg = create_sigalg(signature); if (!sigalg) goto err; decompalg = create_decompress(payload); if (!decompalg && payload->compression != STREAM_COMPRESS_NONE) goto err; if (!send_stream(program, notify, payload, sigalg, decompalg)) goto err; if (!signature_update(sigalg, payload->mem.stream->extra_salt, payload->mem.stream->extra_salt_len) || !signature_update(sigalg, signature->shdr->salt, sizeof signature->shdr->salt) || !signature_update(sigalg, signature->hhdr, sizeof *signature->hhdr)) goto err; if (signature->mem.len && !verify_signature(signature, sigalg)) goto err; if (!finish_stream(program, payload, sigalg)) goto err; signature_free(sigalg); return true; err: decompression_free(decompalg); signature_free(sigalg); return false; }
int detached_gpg_verify(const char *content, size_t len, const char *signature, size_t signature_len, const char *keyring) { int fd; const char *tmpdir; char *tempsig; ssize_t ret; if (gpg_cmd == NULL) { warnx("GPG variable not set, failing signature check"); return -1; } if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = "/tmp"; tempsig = xasprintf("%s/pkg_install.XXXXXX", tmpdir); fd = mkstemp(tempsig); if (fd == -1) { warnx("Creating temporary file for GPG signature failed"); return -1; } while (signature_len) { ret = write(fd, signature, signature_len); if (ret == -1) err(EXIT_FAILURE, "Write to GPG failed"); if (ret == 0) errx(EXIT_FAILURE, "Short write to GPG"); signature_len -= ret; signature += ret; } verify_signature(content, len, keyring, tempsig); unlink(tempsig); close(fd); free(tempsig); return 0; }
static gpg_error_t collect_signature (void *cookie, const char *data) { receive_ctx_t ctx = cookie; if (!ctx->signature) if (!(ctx->signature = es_fopenmem (MAX_SIGNATURE, "w+b,samethread"))) return gpg_error_from_syserror (); if (data) es_fputs (data, ctx->signature); if (es_ferror (ctx->signature)) return gpg_error_from_syserror (); if (!data) { verify_signature (ctx); } return 0; }
int asymmetric_verify(struct key *keyring, const char *sig, int siglen, const char *data, int datalen) { struct public_key_signature pks; struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig; struct key *key; int ret = -ENOMEM; if (siglen <= sizeof(*hdr)) return -EBADMSG; siglen -= sizeof(*hdr); if (siglen != __be16_to_cpu(hdr->sig_size)) return -EBADMSG; if (hdr->hash_algo >= PKEY_HASH__LAST) return -ENOPKG; key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); if (IS_ERR(key)) return PTR_ERR(key); memset(&pks, 0, sizeof(pks)); pks.pkey_hash_algo = hdr->hash_algo; pks.digest = (u8 *)data; pks.digest_size = datalen; pks.nr_mpi = 1; pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); if (pks.rsa.s) ret = verify_signature(key, &pks); mpi_free(pks.rsa.s); key_put(key); pr_debug("%s() = %d\n", __func__, ret); return ret; }
/** * restrict_link_by_signature - Restrict additions to a ring of public keys * @trust_keyring: A ring of keys that can be used to vouch for the new cert. * @type: The type of key being added. * @payload: The payload of the new key. * * Check the new certificate against the ones in the trust keyring. If one of * those is the signing key and validates the new certificate, then mark the * new certificate as being trusted. * * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a * matching parent certificate in the trusted list, -EKEYREJECTED if the * signature check fails or the key is blacklisted and some other error if * there is a matching certificate but the signature check cannot be performed. */ int restrict_link_by_signature(struct key *trust_keyring, const struct key_type *type, const union key_payload *payload) { const struct public_key_signature *sig; struct key *key; int ret; pr_devel("==>%s()\n", __func__); if (!trust_keyring) return -ENOKEY; if (type != &key_type_asymmetric) return -EOPNOTSUPP; sig = payload->data[asym_auth]; if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY; if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) return -EPERM; /* See if we have a key that signed this one. */ key = find_asymmetric_key(trust_keyring, sig->auth_ids[0], sig->auth_ids[1], false); if (IS_ERR(key)) return -ENOKEY; if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags)) ret = -ENOKEY; else ret = verify_signature(key, sig); key_put(key); return ret; }
static void *worker_loop(void *ignored) { bool keep_running = true; while(keep_running) { brine_task_s *task = (brine_task_s *) brine_queue_dequeue(queue); if (!task) { keep_running = false; break; } switch(task->cmd) { case BRINE_STOP: keep_running = false; break; case BRINE_NEW_KEYPAIR: generate_keypair(task); break; case BRINE_NEW_KEYPAIR_FROM_SEED: generate_keypair_from_seed(task); break; case BRINE_SIGN_MSG: sign_message(task); break; case BRINE_VERIFY: verify_signature(task); break; case BRINE_TO_BINARY: keypair_to_binary(task); break; case BRINE_TO_KEYPAIR: binary_to_keypair(task); break; default: break; } brine_task_destroy(&task); } return NULL; }
TEST_FIXTURE(HandshakeFixture, VerifiedSignatureIsHMAC) { int err = verify_signature(signature, pubkey, expected_hmac); CHECK_EQUAL(0, err); }
static themis_status_t secure_session_finish_server(secure_session_t *session_ctx, const void *data, size_t data_length, void *output, size_t *output_length) { const soter_container_hdr_t *proto_message = data; soter_container_hdr_t *response_message; themis_status_t res; const uint8_t *mac; size_t mac_length = 0; const uint8_t *signature; size_t signature_length; soter_kdf_context_buf_t sign_data[4]; uint8_t ecdh_key[1024]; size_t ecdh_key_length = sizeof(ecdh_key); uint8_t shared_secret[1024]; size_t shared_secret_length = sizeof(shared_secret); if (data_length < sizeof(soter_container_hdr_t)) { return THEMIS_INVALID_PARAMETER; } if (memcmp(proto_message->tag, THEMIS_SESSION_PROTO_TAG, SOTER_CONTAINER_TAG_LENGTH)) { return THEMIS_INVALID_PARAMETER; } if (data_length < (soter_container_data_size(proto_message) + sizeof(soter_container_hdr_t))) { return THEMIS_INVALID_PARAMETER; } if (THEMIS_SUCCESS != soter_verify_container_checksum(proto_message)) { return THEMIS_INVALID_PARAMETER; } /* Get length of used mac */ res = compute_mac(session_ctx->peer.ecdh_key, session_ctx->peer.ecdh_key_length, NULL, 0, NULL, &mac_length); if (THEMIS_BUFFER_TOO_SMALL != res) { return res; } signature_length = soter_container_data_size(proto_message) - mac_length; signature = soter_container_const_data(proto_message); mac = signature + signature_length; res = soter_asym_ka_export_key(&(session_ctx->ecdh_ctx), ecdh_key, &ecdh_key_length, false); if (THEMIS_SUCCESS != res) { return res; } sign_data[0].data = session_ctx->peer.ecdh_key; sign_data[0].length = session_ctx->peer.ecdh_key_length; sign_data[1].data = ecdh_key; sign_data[1].length = ecdh_key_length; sign_data[2].data = session_ctx->peer.id; sign_data[2].length = session_ctx->peer.id_length; sign_data[3].data = session_ctx->we.id; sign_data[3].length = session_ctx->we.id_length; res = verify_signature(session_ctx->peer.sign_key, session_ctx->peer.sign_key_length, sign_data, 4, signature, signature_length); if (THEMIS_SUCCESS != res) { return res; } res = soter_asym_ka_derive(&(session_ctx->ecdh_ctx), session_ctx->peer.ecdh_key, session_ctx->peer.ecdh_key_length, shared_secret, &shared_secret_length); if (THEMIS_SUCCESS != res) { return res; } res = soter_kdf(NULL, 0, SESSION_ID_GENERATION_LABEL, sign_data, 4, &(session_ctx->session_id), sizeof(session_ctx->session_id)); if (THEMIS_SUCCESS != res) { return res; } sign_data[0].data = (const uint8_t *)(&(session_ctx->session_id)); sign_data[0].length = sizeof(session_ctx->session_id); res = soter_kdf(shared_secret, shared_secret_length, SESSION_MASTER_KEY_GENERATION_LABEL, sign_data, 1, session_ctx->session_master_key, sizeof(session_ctx->session_master_key)); if (THEMIS_SUCCESS != res) { return res; } sign_data[0].data = ecdh_key; sign_data[0].length = ecdh_key_length; sign_data[1].data = (const uint8_t *)(&(session_ctx->session_id)); sign_data[1].length = sizeof(session_ctx->session_id); res = verify_mac(session_ctx->session_master_key, sizeof(session_ctx->session_master_key), sign_data, 2, mac, mac_length); if (THEMIS_SUCCESS != res) { return res; } sign_data[0].data = session_ctx->peer.ecdh_key; sign_data[0].length = session_ctx->peer.ecdh_key_length; /* we will reuse ecdh_key buffer for mac response computation */ ecdh_key_length = sizeof(ecdh_key) - sizeof(soter_container_hdr_t); response_message = (soter_container_hdr_t *)ecdh_key; res = compute_mac(session_ctx->session_master_key, sizeof(session_ctx->session_master_key), sign_data, 2, soter_container_data(response_message), &ecdh_key_length); if (THEMIS_SUCCESS != res) { return res; } if ((NULL == output) || (*output_length < (ecdh_key_length + sizeof(soter_container_hdr_t)))) { *output_length = ecdh_key_length + sizeof(soter_container_hdr_t); return THEMIS_BUFFER_TOO_SMALL; } *output_length = ecdh_key_length + sizeof(soter_container_hdr_t); res = secure_session_derive_message_keys(session_ctx); if (THEMIS_SUCCESS != res) { return res; } memcpy(response_message->tag, THEMIS_SESSION_PROTO_TAG, SOTER_CONTAINER_TAG_LENGTH); soter_container_set_data_size(response_message, ecdh_key_length); soter_update_container_checksum(response_message); memcpy(output, ecdh_key, soter_container_data_size(response_message) + sizeof(soter_container_hdr_t)); /* "Server mode": negotiation completed */ session_ctx->state_handler = NULL; if (session_ctx->user_callbacks->state_changed) { session_ctx->user_callbacks->state_changed(STATE_ESTABLISHED, session_ctx->user_callbacks->user_data); } return res; }
static themis_status_t secure_session_proceed_client(secure_session_t *session_ctx, const void *data, size_t data_length, void *output, size_t *output_length) { const soter_container_hdr_t *proto_message = data; const soter_container_hdr_t *peer_id; const soter_container_hdr_t *peer_ecdh_key; size_t peer_ecdh_key_length; const uint8_t *signature; size_t signature_length; themis_status_t res = THEMIS_SUCCESS; soter_status_t soter_status; uint8_t sign_key[1024]; /* Should be enough for RSA 8192 which is 512 bytes */ size_t sign_key_length; uint8_t ecdh_key[1024]; size_t ecdh_key_length = sizeof(ecdh_key); const soter_container_hdr_t *peer_sign_key; soter_kdf_context_buf_t sign_data[4]; uint8_t *data_to_send = output; size_t length_to_send; soter_container_hdr_t *container; uint8_t *mac; if (data_length < sizeof(soter_container_hdr_t)) { return THEMIS_INVALID_PARAMETER; } if (memcmp(proto_message->tag, THEMIS_SESSION_PROTO_TAG, SOTER_CONTAINER_TAG_LENGTH)) { return THEMIS_INVALID_PARAMETER; } if (data_length < (soter_container_data_size(proto_message) + sizeof(soter_container_hdr_t))) { return THEMIS_INVALID_PARAMETER; } if (THEMIS_SUCCESS != soter_verify_container_checksum(proto_message)) { return THEMIS_INVALID_PARAMETER; } peer_id = (const soter_container_hdr_t *)soter_container_const_data(proto_message); if (memcmp(peer_id->tag, THEMIS_SESSION_ID_TAG, SOTER_CONTAINER_TAG_LENGTH)) { return THEMIS_INVALID_PARAMETER; } if (THEMIS_SUCCESS != soter_verify_container_checksum(peer_id)) { return THEMIS_INVALID_PARAMETER; } peer_ecdh_key = (const soter_container_hdr_t *)(soter_container_const_data(peer_id) + soter_container_data_size(peer_id)); if (memcmp(peer_ecdh_key->tag, EC_PUB_KEY_PREF, strlen(EC_PUB_KEY_PREF))) { return THEMIS_INVALID_PARAMETER; } peer_ecdh_key_length = ntohl(peer_ecdh_key->size); signature = (const uint8_t *)peer_ecdh_key + peer_ecdh_key_length; signature_length = (const uint8_t *)data + soter_container_data_size(proto_message) + sizeof(soter_container_hdr_t) - signature; if (session_ctx->user_callbacks->get_public_key_for_id(soter_container_const_data(peer_id), soter_container_data_size(peer_id), sign_key, sizeof(sign_key), session_ctx->user_callbacks->user_data)) { return THEMIS_SSESSION_GET_PUB_FOR_ID_CALLBACK_ERROR; } peer_sign_key = (const soter_container_hdr_t *)sign_key; if (memcmp(peer_sign_key->tag, EC_PUB_KEY_PREF, strlen(EC_PUB_KEY_PREF))) { return THEMIS_INVALID_PARAMETER; } sign_key_length = ntohl(peer_sign_key->size); if (sizeof(soter_container_hdr_t) >= sign_key_length) { return THEMIS_INVALID_PARAMETER; } soter_status = soter_asym_ka_export_key(&(session_ctx->ecdh_ctx), ecdh_key, &ecdh_key_length, false); if (THEMIS_SUCCESS != soter_status) { return soter_status; } sign_data[0].data = (const uint8_t *)peer_ecdh_key; sign_data[0].length = peer_ecdh_key_length; sign_data[1].data = ecdh_key; sign_data[1].length = ecdh_key_length; sign_data[2].data = soter_container_const_data(peer_id); sign_data[2].length = soter_container_data_size(peer_id); sign_data[3].data = session_ctx->we.id; sign_data[3].length = session_ctx->we.id_length; res = verify_signature(peer_sign_key, sign_key_length, sign_data, 4, signature, signature_length); if (THEMIS_SUCCESS != res) { return res; } res = secure_session_peer_init(&(session_ctx->peer), soter_container_const_data(peer_id), soter_container_data_size(peer_id), peer_ecdh_key, peer_ecdh_key_length, peer_sign_key, sign_key_length); if (THEMIS_SUCCESS != res) { goto err; } sign_data[0].data = ecdh_key; sign_data[0].length = ecdh_key_length; sign_data[1].data = (const uint8_t *)peer_ecdh_key; sign_data[1].length = peer_ecdh_key_length; sign_data[2].data = session_ctx->we.id; sign_data[2].length = session_ctx->we.id_length; sign_data[3].data = soter_container_const_data(peer_id); sign_data[3].length = soter_container_data_size(peer_id); res = soter_kdf(NULL, 0, SESSION_ID_GENERATION_LABEL, sign_data, 4, &(session_ctx->session_id), sizeof(session_ctx->session_id)); if (THEMIS_SUCCESS != res) { goto err; } /* we will reuse sign_key buffer for shared secret computation */ sign_key_length = sizeof(sign_key); res = soter_asym_ka_derive(&(session_ctx->ecdh_ctx), peer_ecdh_key, peer_ecdh_key_length, sign_key, &sign_key_length); if (THEMIS_SUCCESS != res) { goto err; } sign_data[0].data = (const uint8_t *)(&(session_ctx->session_id)); sign_data[0].length = sizeof(session_ctx->session_id); res = soter_kdf(sign_key, sign_key_length, SESSION_MASTER_KEY_GENERATION_LABEL, sign_data, 1, session_ctx->session_master_key, sizeof(session_ctx->session_master_key)); if (THEMIS_SUCCESS != res) { goto err; } /* restore sign data for signature computation */ sign_data[0].data = ecdh_key; sign_data[0].length = ecdh_key_length; res = compute_signature(session_ctx->we.sign_key, session_ctx->we.sign_key_length, NULL, 0, NULL, &signature_length); if (THEMIS_BUFFER_TOO_SMALL != res) { goto err; } /* we will reuse sign_key_length for mac length retrieval */ res = compute_mac(session_ctx->session_master_key, sizeof(session_ctx->session_master_key), NULL, 0, NULL, &sign_key_length); if (THEMIS_BUFFER_TOO_SMALL != res) { goto err; } length_to_send = sizeof(soter_container_hdr_t) + signature_length + sign_key_length; if ((NULL == output) || (*output_length < length_to_send)) { *output_length = length_to_send; res = THEMIS_BUFFER_TOO_SMALL; goto err; } container = (soter_container_hdr_t *)data_to_send; /* Actual signature may be 1 or 2 bytes less than reported above because leading zeroes are stripped */ length_to_send -= signature_length; res = compute_signature(session_ctx->we.sign_key, session_ctx->we.sign_key_length, sign_data, 4, soter_container_data(container), &signature_length); if (THEMIS_SUCCESS != res) { goto err; } length_to_send += signature_length; mac = soter_container_data(container) + signature_length; sign_data[0].data = (const uint8_t *)(session_ctx->peer.ecdh_key); sign_data[0].length = session_ctx->peer.ecdh_key_length; sign_data[1].data = (const uint8_t *)(&(session_ctx->session_id)); sign_data[1].length = sizeof(session_ctx->session_id); res = compute_mac(session_ctx->session_master_key, sizeof(session_ctx->session_master_key), sign_data, 2, mac, &sign_key_length); if (THEMIS_SUCCESS != res) { goto err; } *output_length = length_to_send; memcpy(container->tag, THEMIS_SESSION_PROTO_TAG, SOTER_CONTAINER_TAG_LENGTH); soter_container_set_data_size(container, length_to_send - sizeof(soter_container_hdr_t)); soter_update_container_checksum(container); /* "Client mode": waiting final confirmation from server */ session_ctx->state_handler = secure_session_finish_client; err: if (THEMIS_SUCCESS != res) { secure_session_peer_cleanup(&(session_ctx->peer)); } return res; }
static themis_status_t secure_session_accept(secure_session_t *session_ctx, const void *data, size_t data_length, void *output, size_t *output_length) { const soter_container_hdr_t *proto_message = data; const soter_container_hdr_t *peer_id; const soter_container_hdr_t *peer_ecdh_key; size_t peer_ecdh_key_length; const uint8_t *signature; size_t signature_length; themis_status_t res = THEMIS_SUCCESS; soter_status_t soter_status; uint8_t sign_key[1024]; /* Should be enough for RSA 8192 which is 512 bytes */ size_t sign_key_length; const soter_container_hdr_t *peer_sign_key; soter_kdf_context_buf_t sign_data[4]; uint8_t *data_to_send = output; size_t length_to_send; size_t ecdh_key_length = 0; soter_container_hdr_t *container; if (data_length < sizeof(soter_container_hdr_t)) { return THEMIS_INVALID_PARAMETER; } if (memcmp(proto_message->tag, THEMIS_SESSION_PROTO_TAG, SOTER_CONTAINER_TAG_LENGTH)) { return THEMIS_INVALID_PARAMETER; } if (data_length < (soter_container_data_size(proto_message) + sizeof(soter_container_hdr_t))) { return THEMIS_INVALID_PARAMETER; } if (THEMIS_SUCCESS != soter_verify_container_checksum(proto_message)) { return THEMIS_INVALID_PARAMETER; } peer_id = (const soter_container_hdr_t *)soter_container_const_data(proto_message); if (memcmp(peer_id->tag, THEMIS_SESSION_ID_TAG, SOTER_CONTAINER_TAG_LENGTH)) { return THEMIS_INVALID_PARAMETER; } if (THEMIS_SUCCESS != soter_verify_container_checksum(peer_id)) { return THEMIS_INVALID_PARAMETER; } peer_ecdh_key = (const soter_container_hdr_t *)(soter_container_const_data(peer_id) + soter_container_data_size(peer_id)); if (memcmp(peer_ecdh_key->tag, EC_PUB_KEY_PREF, strlen(EC_PUB_KEY_PREF))) { return THEMIS_INVALID_PARAMETER; } peer_ecdh_key_length = soter_container_data_size(peer_ecdh_key) + sizeof(soter_container_hdr_t); signature = (const uint8_t *)peer_ecdh_key + peer_ecdh_key_length; signature_length = (const uint8_t *)data + soter_container_data_size(proto_message) + sizeof(soter_container_hdr_t) - signature; if (session_ctx->user_callbacks->get_public_key_for_id(soter_container_const_data(peer_id), soter_container_data_size(peer_id), sign_key, sizeof(sign_key), session_ctx->user_callbacks->user_data)) { return THEMIS_SSESSION_GET_PUB_FOR_ID_CALLBACK_ERROR; } peer_sign_key = (const soter_container_hdr_t *)sign_key; if (memcmp(peer_sign_key->tag, EC_PUB_KEY_PREF, strlen(EC_PUB_KEY_PREF))) { return THEMIS_INVALID_PARAMETER; } sign_key_length = ntohl(peer_sign_key->size); if (sizeof(soter_container_hdr_t) >= sign_key_length) { return THEMIS_INVALID_PARAMETER; } sign_data[0].data = (const uint8_t *)peer_ecdh_key; sign_data[0].length = peer_ecdh_key_length; res = verify_signature(peer_sign_key, sign_key_length, sign_data, 1, signature, signature_length); if (THEMIS_SUCCESS != res) { return res; } /* Preparing to send response */ res = compute_signature(session_ctx->we.sign_key, session_ctx->we.sign_key_length, NULL, 0, NULL, &signature_length); if (THEMIS_BUFFER_TOO_SMALL != res) { return res; } soter_status = soter_asym_ka_export_key(&(session_ctx->ecdh_ctx), NULL, &ecdh_key_length, false); if (THEMIS_BUFFER_TOO_SMALL != soter_status) { return soter_status; } length_to_send = 2 * sizeof(soter_container_hdr_t) + session_ctx->we.id_length + ecdh_key_length + signature_length; if ((NULL == output) || (*output_length < length_to_send)) { *output_length = length_to_send; return THEMIS_BUFFER_TOO_SMALL; } res = secure_session_peer_init(&(session_ctx->peer), soter_container_const_data(peer_id), soter_container_data_size(peer_id), peer_ecdh_key, peer_ecdh_key_length, peer_sign_key, sign_key_length); if (THEMIS_SUCCESS != res) { goto err; } /* Storing ID in a container */ container = (soter_container_hdr_t *)data_to_send + 1; memcpy(container->tag, THEMIS_SESSION_ID_TAG, SOTER_CONTAINER_TAG_LENGTH); soter_container_set_data_size(container, session_ctx->we.id_length); memcpy(soter_container_data(container), session_ctx->we.id, session_ctx->we.id_length); soter_update_container_checksum(container); /* Moving back to beginning of allocated buffer */ container = (soter_container_hdr_t *)data_to_send; soter_status = soter_asym_ka_export_key(&(session_ctx->ecdh_ctx), data_to_send + (2 * sizeof(soter_container_hdr_t)) + session_ctx->we.id_length, &ecdh_key_length, false); if (THEMIS_SUCCESS != soter_status) { res = soter_status; goto err; } sign_data[0].data = data_to_send + (2 * sizeof(soter_container_hdr_t)) + session_ctx->we.id_length; sign_data[0].length = ecdh_key_length; sign_data[1].data = session_ctx->peer.ecdh_key; sign_data[1].length = session_ctx->peer.ecdh_key_length; sign_data[2].data = session_ctx->we.id; sign_data[2].length = session_ctx->we.id_length; sign_data[3].data = session_ctx->peer.id; sign_data[3].length = session_ctx->peer.id_length; /* Actual signature may be 1 or 2 bytes less than reported above because leading zeroes are stripped */ length_to_send -= signature_length; res = compute_signature(session_ctx->we.sign_key, session_ctx->we.sign_key_length, sign_data, 4, data_to_send + (2 * sizeof(soter_container_hdr_t)) + session_ctx->we.id_length + ecdh_key_length, &signature_length); if (THEMIS_SUCCESS != res) { goto err; } length_to_send += signature_length; *output_length = length_to_send; memcpy(container->tag, THEMIS_SESSION_PROTO_TAG, SOTER_CONTAINER_TAG_LENGTH); soter_container_set_data_size(container, length_to_send - sizeof(soter_container_hdr_t)); soter_update_container_checksum(container); /* "Server mode": waiting response from the client */ session_ctx->state_handler = secure_session_finish_server; if (session_ctx->user_callbacks->state_changed) { session_ctx->user_callbacks->state_changed(STATE_NEGOTIATING, session_ctx->user_callbacks->user_data); } err: if (THEMIS_SUCCESS != res) { secure_session_peer_cleanup(&(session_ctx->peer)); } return res; }
static int verify_private_key_ownership(struct openssl_session_auth_context* ctx, const char* private_key, int private_key_length, const char* client_certificate, int client_certificate_length) { char* x_buffer = NULL, *y_buffer = NULL, *concat_buffer = NULL; int ret, tmp; char* yx_signature = NULL, *xy_signature = NULL; int yx_signature_length, xy_signature_length; x_buffer = malloc(XY_RANDOM_DATA_LENGTH); y_buffer = malloc(XY_RANDOM_DATA_LENGTH); concat_buffer = malloc(2*XY_RANDOM_DATA_LENGTH); if ( !x_buffer || !y_buffer || !concat_buffer ) goto failed; get_random_key(x_buffer, XY_RANDOM_DATA_LENGTH); if ( write_u32(ctx, XY_RANDOM_DATA_LENGTH) != 4 ) { printf("Failed to x buffer size\n"); goto failed; } if ( openssl_local_write(ctx, x_buffer, XY_RANDOM_DATA_LENGTH) != XY_RANDOM_DATA_LENGTH ) { printf("Failed to send x buffer\n"); goto failed; } if ( openssl_local_read(ctx, XY_RANDOM_DATA_LENGTH, y_buffer, &tmp) < XY_RANDOM_DATA_LENGTH ) { printf( "Failed to read y buffer\n"); goto failed; } memcpy(concat_buffer,y_buffer, XY_RANDOM_DATA_LENGTH); memcpy(concat_buffer+XY_RANDOM_DATA_LENGTH,x_buffer, XY_RANDOM_DATA_LENGTH); yx_signature_length = read_u32(ctx); if ( yx_signature_length == READ_ERROR ) { printf("Failed to read yx signature length\n"); goto failed; } yx_signature = malloc(yx_signature_length); if ( !yx_signature ) goto failed; if ( openssl_local_read(ctx, yx_signature_length, yx_signature, &tmp) < yx_signature_length ) { printf("Failed to read yx signature\n"); goto failed; } ret = verify_signature(client_certificate, client_certificate_length, concat_buffer, 2*XY_RANDOM_DATA_LENGTH, yx_signature, yx_signature_length); if ( ret ) { printf("Failed to verify yx signature\n"); goto failed; } memcpy(concat_buffer,x_buffer, XY_RANDOM_DATA_LENGTH); memcpy(concat_buffer+XY_RANDOM_DATA_LENGTH,y_buffer, XY_RANDOM_DATA_LENGTH); ret = sign_data(private_key, private_key_length, concat_buffer, 2*XY_RANDOM_DATA_LENGTH, &xy_signature, &xy_signature_length); if ( ret ) { printf("Failed to sign xy buffer\n"); goto failed; } if ( write_u32(ctx, xy_signature_length) != 4) { printf("Failed to send xy signature length\n"); goto failed; } /* Send server certificate */ if ( openssl_local_write(ctx, xy_signature, xy_signature_length) != xy_signature_length ) { printf("Failed to send xy signature\n"); goto failed; } goto done; failed: ret = -1; done: free(x_buffer); free(y_buffer); free(concat_buffer); free(xy_signature); free(yx_signature); return ret; };
/** * Check the trust on one PKCS#7 SignedInfo block. */ int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo, struct key *trust_keyring) { struct public_key_signature *sig = &sinfo->sig; struct x509_certificate *x509, *last = NULL, *p; struct key *key; bool trusted; int ret; kenter(",%u,", sinfo->index); for (x509 = sinfo->signer; x509; x509 = x509->signer) { if (x509->seen) { if (x509->verified) { trusted = x509->trusted; goto verified; } kleave(" = -ENOKEY [cached]"); return -ENOKEY; } x509->seen = true; /* Look to see if this certificate is present in the trusted * keys. */ key = pkcs7_request_asymmetric_key( trust_keyring, x509->subject, strlen(x509->subject), x509->fingerprint, strlen(x509->fingerprint)); if (!IS_ERR(key)) /* One of the X.509 certificates in the PKCS#7 message * is apparently the same as one we already trust. * Verify that the trusted variant can also validate * the signature on the descendant. */ goto matched; if (key == ERR_PTR(-ENOMEM)) return -ENOMEM; /* Self-signed certificates form roots of their own, and if we * don't know them, then we can't accept them. */ if (x509->next == x509) { kleave(" = -ENOKEY [unknown self-signed]"); return -ENOKEY; } might_sleep(); last = x509; sig = &last->sig; } /* No match - see if the root certificate has a signer amongst the * trusted keys. */ if (!last || !last->issuer || !last->authority) { kleave(" = -ENOKEY [no backref]"); return -ENOKEY; } key = pkcs7_request_asymmetric_key( trust_keyring, last->issuer, strlen(last->issuer), last->authority, strlen(last->authority)); if (IS_ERR(key)) return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY; x509 = last; matched: ret = verify_signature(key, sig); trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags); key_put(key); if (ret < 0) { if (ret == -ENOMEM) return ret; kleave(" = -EKEYREJECTED [verify %d]", ret); return -EKEYREJECTED; } verified: x509->verified = true; for (p = sinfo->signer; p != x509; p = p->signer) { p->verified = true; p->trusted = trusted; } sinfo->trusted = trusted; kleave(" = 0"); return 0; }