int verify(const char *command, int argc, char **argv) { int ret = 1; unsigned char signature[sizeof(ecdsa_signature_t)]; set pubkeys, signatures; set_init(&pubkeys, sizeof(ecc_25519_work_t), 5); set_init(&signatures, sizeof(signature), 5); size_t min_good_signatures = 1; int opt; while ((opt = getopt(argc, argv, "s:p:n:")) != -1) { ecc_int256_t pubkey_packed; ecc_25519_work_t pubkey; switch (opt) { case 's': if (!parsehex(signature, optarg, sizeof(signature))) { fprintf(stderr, "Error while reading signature %s\n", optarg); break; } if (!set_add(&signatures, signature)) { fprintf(stderr, "Error in array_add\n"); goto out; } break; case 'p': if (!parsehex(pubkey_packed.p, optarg, 32)) { fprintf(stderr, "Error while reading pubkey %s\n", optarg); break; } int ok = ecc_25519_load_packed_legacy(&pubkey, &pubkey_packed); if (!ok || !ecdsa_is_valid_pubkey(&pubkey)) { fprintf(stderr, "Invalid pubkey %s\n", optarg); break; } if (!set_add(&pubkeys, &pubkey)) { fprintf(stderr, "Error in array_add\n"); goto out; } break; case 'n': min_good_signatures = atoi(optarg); } } if (optind > argc) { fprintf(stderr, "Usage: %s [-s signature ...] [-p pubkey ...] [-n num] file\n", command); goto out; } ecc_int256_t hash; if (!sha256_file((optind <= argc) ? argv[optind] : NULL, hash.p)) { fprintf(stderr, "Error while hashing file\n"); goto out; } { ecdsa_verify_context_t ctxs[signatures.size]; for (size_t i = 0; i < signatures.size; i++) ecdsa_verify_prepare_legacy(&ctxs[i], &hash, SET_INDEX(signatures, i)); size_t good_signatures = ecdsa_verify_list_legacy(ctxs, signatures.size, pubkeys.content, pubkeys.size); if (good_signatures >= min_good_signatures) ret = 0; } out: set_destroy(&pubkeys); set_destroy(&signatures); return ret; }
void load_settings(struct settings *settings) { struct uci_context *ctx = uci_alloc_context(); if (!ctx) { fprintf(stderr, "autoupdater: error: failed to allocate UCI context\n"); abort(); } ctx->flags &= ~UCI_FLAG_STRICT; struct uci_package *p; struct uci_section *s; if (uci_load(ctx, "autoupdater", &p) != UCI_OK) { fputs("autoupdater: error: unable to load UCI package\n", stderr); exit(1); } s = uci_lookup_section(ctx, p, "settings"); if (!s || strcmp(s->type, "autoupdater")) { fputs("autoupdater: error: unable to load UCI settings\n", stderr); exit(1); } const char *enabled = uci_lookup_option_string(ctx, s, "enabled"); if ((!enabled || strcmp(enabled, "1")) && !settings->force) { fputs("autoupdater is disabled\n", stderr); exit(0); } const char *version_file = uci_lookup_option_string(ctx, s, "version_file"); if (version_file) settings->old_version = read_one_line(version_file); if (!settings->branch) settings->branch = uci_lookup_option_string(ctx, s, "branch"); if (!settings->branch) { fputs("autoupdater: error: no branch given in settings or command line\n", stderr); exit(1); } struct uci_section *branch = uci_lookup_section(ctx, p, settings->branch); if (!branch || strcmp(branch->type, "branch")) { fprintf(stderr, "autoupdater: error: unable to load branch configuration for branch '%s'\n", settings->branch); exit(1); } settings->good_signatures = load_positive_number(ctx, branch, "good_signatures"); if (settings->n_mirrors == 0) settings->mirrors = load_string_list(ctx, branch, "mirror", &settings->n_mirrors); const char **pubkeys_str = load_string_list(ctx, branch, "pubkey", &settings->n_pubkeys); settings->pubkeys = safe_malloc(settings->n_pubkeys * sizeof(ecc_25519_work_t)); size_t ignored_keys = 0; for (size_t i = 0; i < settings->n_pubkeys; i++) { ecc_int256_t pubkey_packed; if (!pubkeys_str[i]) goto pubkey_fail; if (!parsehex(pubkey_packed.p, pubkeys_str[i], 32)) goto pubkey_fail; if (!ecc_25519_load_packed_legacy(&settings->pubkeys[i-ignored_keys], &pubkey_packed)) goto pubkey_fail; if (!ecdsa_is_valid_pubkey(&settings->pubkeys[i-ignored_keys])) goto pubkey_fail; continue; pubkey_fail: fprintf(stderr, "autoupdater: warning: ignoring invalid public key %s\n", pubkeys_str[i]); ignored_keys++; } settings->n_pubkeys -= ignored_keys; /* Don't free UCI context, we still reference values from it */ }