static void http_decode(const char *in, char **rp) { size_t i, j, sz; sz = strlen(in); *rp = kcalloc(sz + 1, 1); for (i = j = 0; i < sz; i++, j++) { if ('+' == in[i]) { (*rp)[j] = ' '; continue; } else if ('%' != in[i]) { (*rp)[j] = in[i]; continue; } if ('\0' == in[i + 1] || '\0' == in[i + 2] || ! isalnum((int)in[i + 1]) || ! isalnum((int)in[i + 2])) { (*rp)[j] = in[i]; continue; } (*rp)[j] = parsehex(in[i + 1]) << 4 | parsehex(in[i + 2]); i += 2; } }
/* * Note that this implementation does not (and should not!) obey * locale settings; you cannot simply substitute strtol here, since * it does obey locale. */ static int64_t mtree_atol16(char **p) { int64_t l, limit, last_digit_limit; int base, digit, sign; base = 16; if (**p == '-') { sign = -1; limit = ((uint64_t)(INT64_MAX) + 1) / base; last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base; ++(*p); } else { sign = 1; limit = INT64_MAX / base; last_digit_limit = INT64_MAX % base; } l = 0; digit = parsehex(**p); while (digit >= 0 && digit < base) { if (l > limit || (l == limit && digit > last_digit_limit)) return (sign < 0) ? INT64_MIN : INT64_MAX; l = (l * base) + digit; digit = parsehex(*++(*p)); } return (sign < 0) ? -l : l; }
static int dlist_tohex64(struct dlist *dl, bit64 *valp) { const char *end = NULL; bit64 newval; if (!dl) return 0; switch (dl->type) { case DL_ATOM: case DL_BUF: if (parsehex(dl->sval, &end, dl->nval, &newval)) return 0; if (end - dl->sval != (int)dl->nval) return 0; /* successfully parsed - switch to a numeric value */ dlist_makehex64(dl, newval); break; case DL_NUM: case DL_HEX: case DL_DATE: dl->type = DL_HEX; break; default: return 0; } if (valp) *valp = dl->nval; return 1; }
void sign(int argc, char **argv) { ecc_int256_t secret, hash, k, krecip, r, s, tmp; ecc_25519_work_t kG; if (argc != 2) exit_error(1, 0, "Usage: ecdsautil sign file (secret is read from stdin)"); if (!sha256_file(argv[1], tmp.p)) exit_error(1, 0, "Error while hashing file"); char secret_string[65]; if (fgets(secret_string, sizeof(secret_string), stdin) == NULL) exit_error(1, 0, "Error reading secret"); if (!parsehex(secret.p, secret_string, 32)) exit_error(1, 0, "Error reading secret"); // Reduce hash (instead of clearing 3 bits) ecc_25519_gf_reduce(&hash, &tmp); // Generate k generate_k(k.p, secret.p, tmp.p); ecc_25519_gf_sanitize_secret(&k, &k); // calculate k^(-1) ecc_25519_gf_recip(&krecip, &k); // calculate kG = k * base point ecc_25519_scalarmult_base(&kG, &k); // store x coordinate of kG in r ecc_25519_store_xy(&tmp, NULL, &kG); ecc_25519_gf_reduce(&r, &tmp); if (ecc_25519_gf_is_zero(&r)) exit_error(1, 0, "Error: r is zero (this should never happen)"); // tmp = r * secret ecc_25519_gf_mult(&tmp, &r, &secret); // s = hash + tmp = hash + r * secret ecc_25519_gf_add(&s, &hash, &tmp); // tmp = krecip * s = k^(-1) * s ecc_25519_gf_mult(&tmp, &krecip, &s); // mod n (order of G) ecc_25519_gf_reduce(&s, &tmp); if (ecc_25519_gf_is_zero(&s)) exit_error(1, 0, "Error: s is zero (this should never happen)"); hexdump(stdout, r.p, 32); hexdump(stdout, s.p, 32); puts(""); }
void show_key(void) { char secret_string[65]; ecc_int256_t pubkey, secret; if (fgets(secret_string, sizeof(secret_string), stdin) == NULL) goto secret_error; if (!parsehex(secret.p, secret_string, 32)) goto secret_error; ecdsa_public_from_secret(&pubkey, &secret); output_key(&pubkey); return; secret_error: exit_error(1, 0, "Error reading secret"); }
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; }
static void parseclose(void *dat, const XML_Char *s) { struct parse *p = dat; size_t i, j, sz, len; int c; char **array; switch (calelem_find(s)) { case (CALELEM_CALENDAR_MULTIGET): case (CALELEM_CALENDAR_QUERY): case (CALELEM_PROPERTYUPDATE): case (CALELEM_PROPFIND): /* Clear our parsing context. */ XML_SetDefaultHandler(p->xp, NULL); XML_SetElementHandler(p->xp, NULL, NULL); break; case (CALELEM_HREF): if (0 == p->buf.sz) break; /* * According to the WebDAV RFC 4918, we need to URL * decode this. */ array = reallocarray(p->p->hrefs, p->p->hrefsz + 1, sizeof(char *)); if (NULL == array) { caldav_err(p, "memory exhausted"); break; } p->p->hrefs = array; sz = strlen(p->buf.buf); len = sz + 1; p->p->hrefs[p->p->hrefsz] = calloc(len, 1); if (NULL == p->p->hrefs[p->p->hrefsz]) { caldav_err(p, "memory exhausted"); break; } p->p->hrefsz++; for (i = j = 0; i < sz; i++, j++) { c = p->buf.buf[i]; if ('+' == c) { p->p->hrefs[p->p->hrefsz - 1][j] = ' '; continue; } else if ('%' != c) { p->p->hrefs[p->p->hrefsz - 1][j] = c; continue; } if ('\0' == p->buf.buf[i + 1] || '\0' == p->buf.buf[i + 2] || ! isalnum(p->buf.buf[i + 1]) || ! isalnum(p->buf.buf[i + 2])) { caldav_err(p, "bad percent-encoding"); break; } p->p->hrefs[p->p->hrefsz - 1][j] = parsehex(p->buf.buf[i + 1]) << 4 | parsehex(p->buf.buf[i + 2]); i += 2; } XML_SetDefaultHandler(p->xp, NULL); break; default: break; } }
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 */ }
int main(int argc, char *argv[]) { unsigned char signature[64]; array pubkeys, signatures; array_init(&pubkeys, sizeof(ecc_25519_work_t), 5); array_init(&signatures, sizeof(signature), 5); int 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, 64)) { fprintf(stderr, "Error while reading signature %s\n", optarg); break; } if (!array_add(&signatures, signature, sizeof(signature))) { fprintf(stderr, "Error in array_add\n"); goto error_out; } break; case 'p': if (!parsehex(pubkey_packed.p, optarg, 32)) { fprintf(stderr, "Error while reading pubkey %s\n", optarg); break; } int ret; ret = ecc_25519_load_packed(&pubkey, &pubkey_packed); if (!ret || !ecdsa_is_valid_pubkey(&pubkey)) { fprintf(stderr, "Invalid pubkey %s\n", optarg); break; } if (!array_add(&pubkeys, &pubkey, sizeof(ecc_25519_work_t))) { fprintf(stderr, "Error in array_add\n"); goto error_out; } break; case 'n': min_good_signatures = atoi(optarg); } } if (optind >= argc) { fprintf(stderr, "Usage: %s [-s signature ...] [-p pubkey ...] [-n num] file\n", argv[0]); goto error_out; } ecc_int256_t hash; if (!sha256_file(argv[optind], hash.p)) { fprintf(stderr, "Error while hashing file\n"); goto error_out; } int good_signatures = 0; array_nub(&pubkeys); array_nub(&signatures); for (int i = 0; i < signatures.size; i++) { unsigned char *signature; ecdsa_verify_context ctx; signature = ARRAY_INDEX(signatures, i); ecdsa_verify_prepare(&ctx, &hash, signature); for (int i = 0; i < pubkeys.size; i++) { ecc_25519_work_t *pubkey; pubkey = ARRAY_INDEX(pubkeys, i); if (ecdsa_verify_with_pubkey(&ctx, pubkey)) { good_signatures++; array_rm(&pubkeys, i); break; } } } array_destroy(&pubkeys); array_destroy(&signatures); if (good_signatures >= min_good_signatures) return 0; return 1; error_out: array_destroy(&pubkeys); array_destroy(&signatures); return 1; }
static int run_file(const char *filename) { FILE *tv; char buf[1024], *eol; const char *cp, *errstr; int lnum = 0, fail = 0; u_char *key, *plaintext, *ciphertext; u_int keylen, textlen, tmp; int blocksize, keysize, test; if ((tv = fopen(filename, "r")) == NULL) err(1, "fopen(\"%s\")", filename); keylen = textlen = tmp = 0; key = ciphertext = plaintext = NULL; blocksize = keysize = test = -1; while ((fgets(buf, sizeof(buf), tv)) != NULL) { lnum++; eol = buf + strlen(buf) - 1; if (*eol != '\n') errx(1, "line %d: too long", lnum); if (eol > buf && *(eol - 1) == '\r') eol--; *eol = '\0'; if ((cp = startswith(buf, "BLOCKSIZE=")) != NULL) { if (blocksize != -1) errx(1, "line %d: blocksize already set", lnum); blocksize = (int)strtonum(cp, 128, 128, &errstr); if (errstr) errx(1, "line %d: blocksize is %s: \"%s\"", lnum, errstr, cp); } else if ((cp = startswith(buf, "KEYSIZE=")) != NULL) { if (keysize != -1) errx(1, "line %d: keysize already set", lnum); keysize = (int)strtonum(cp, 128, 256, &errstr); if (errstr) errx(1, "line %d: keysize is %s: \"%s\"", lnum, errstr, cp); if (keysize != 128 && keysize != 256) errx(1, "line %d: XXX only 128 or 256 " "bit keys for now (keysize = %d)", lnum, keysize); } else if ((cp = startswith(buf, "PT=")) != NULL) { if (plaintext != NULL) free(plaintext); parsehex(cp, &plaintext, &tmp); if (tmp * 8 != (u_int)blocksize) errx(1, "line %d: plaintext len %u != " "blocklen %d", lnum, tmp, blocksize); if (textlen != 0) { if (textlen != tmp) errx(1, "line %d: plaintext len %u != " "ciphertext len %d", lnum, tmp, textlen); } else textlen = tmp; } else if ((cp = startswith(buf, "CT=")) != NULL) { if (ciphertext != NULL) free(ciphertext); parsehex(cp, &ciphertext, &tmp); if (tmp * 8 != (u_int)blocksize) errx(1, "line %d: ciphertext len %u != " "blocklen %d", lnum, tmp, blocksize); if (textlen != 0) { if (textlen != tmp) errx(1, "line %d: ciphertext len %u != " "plaintext len %d", lnum, tmp, textlen); } else textlen = tmp; } else if ((cp = startswith(buf, "KEY=")) != NULL) { if (key != NULL) free(key); parsehex(cp, &key, &keylen); if (keylen * 8 != (u_int)keysize) errx(1, "line %d: ciphertext len %u != " "blocklen %d", lnum, tmp, textlen); } else if ((cp = startswith(buf, "TEST=")) != NULL) { if (plaintext == NULL || ciphertext == NULL || key == NULL || blocksize == -1 || keysize == -1) { if (test != -1) errx(1, "line %d: new test before " "parameters", lnum); goto parsetest; } /* do the tests */ fail += do_tests(filename, test, key, keylen, plaintext, ciphertext, textlen); parsetest: test = (int)strtonum(cp, 0, 65536, &errstr); if (errstr) errx(1, "line %d: test is %s: \"%s\"", lnum, errstr, cp); } else { /* don't care */ continue; } } fclose(tv); return fail; }